I have a class with a Django ImageField and I have been struggling to decide between two alternatives for storing that field's upload_to
function. The first approach is pretty straightforward. The function is defined on the module level (c.f. https://stackoverflow.com/a/1190866/790075, https://stackoverflow.com/a/3091864/790075):
def get_car_photo_file_path(instance, filename):
ext = filename.split('.')[-1]
filename = "%s.%s" % (uuid.uuid4(), ext) # chance of collision <1e-50
return os.path.join('uploads/cars/photos', filename)
class CarPhoto(models.Model):
photo = models.ImageField(upload_to=get_car_photo_file_path)
This is simple and easy to understand, but pollutes the module scope by adding a function that is really only pertinent to the CarPhoto class.
In the second approach, I use the callable-class pattern to associate the function more closely with the CarPhoto class. This moves the upload_to
function out of module scope but feels unnecessarily complicated.
class CarPhoto(models.Model):
class getCarPhotoFilePath():
# Either use this pattern or associate function with module instead of this class
def __call__(self, instance, filename):
ext = filename.split('.')[-1]
filename = "%s.%s" % (uuid.uuid4(), ext) # chance of collision <1e-50
return os.path.join('uploads/cars/photos', filename)
photo = models.ImageField(upload_to=getCarPhotoFilePath())
I have seen suggestions for using the @staticmethod
and @classmethod
decorators (c.f. https://stackoverflow.com/a/9264153/790075), but I find that when I do this the function never executes and the filename ends up looking like: /path/to/file/<classmethod object>
, with the method object embedded in the file path, which is certainly not intended!
Which of these is the preferred pattern? Is there a better way?