Django: Upload files to a dynamic path

For the projects I'm working on, we have a reusable "image file" model which stores information about an image (such as height, width, hash, image type, etc) and automatically stashes it to Amazon S3.

Any time you want to use an image in another model, you can just refer to it through a foreign key.

class BasicImage(models.Model):
caption = models.CharField(max_length=300, blank=True)
# ...
image = models.ImageField(storage = s3_storage, upload_to = "images", max_length = 500)

def __unicode__(self):
return "%s - %s" % (self.caption, self.image)

And an example of a  model which uses BasicImage.

class UserProfile(models.Model):
# ...
profile_picture = models.ForeignKey(BasicImage)

Whenever a user uploads a profile picture, it'll be uploaded to a folder called "images", along with every other image file. That's fine and dandy if you're ok with mixing user profile pictures with other images (such as company logos or user photos).

However, most people would like to separate things out a bit. Here's a relatively clean way of preventing a huge binary mess. (Key points are listed below)

def _image_upload_path(instance, filename):
# To customise the path which the image saves to.
return instance.get_upload_path(filename)


class BasicImage(models.Model):
caption = models.CharField(max_length=300, blank=True)
# ...
image = models.ImageField(storage = s3_storage, upload_to = _image_upload_path, max_length = 500)

def __unicode__(self):
return "%s - %s" % (self.caption, self.image)

def get_upload_path(self, filename):
return "dimg/%s" % filename


# Required to add new files to a different path
class UserProfileImage(BasicImage):
class Meta:
proxy = True # So this model doesn't actually need a new table

def get_upload_path(self, filename):
return "avatars/%s" % filename


# Updated user model so any pictures will be uploaded to /avatars folder
class UserProfile(models.Model):
user = models.OneToOneField(User, primary_key = True)
# ...
profile_picture = models.ForeignKey(UserProfileImage)

 

Take note of the differences:

  • Create a helper function called _image_upload_path()
  • Add BasicImage.get_upload_path(self, filename)
  • You'll need to use BasicImage as a base class for any other image models
  • Other image models should be a proxy class unless they contain additional information
  • Override get_upload_path() in your subclasses if you wish to customise the upload folder

abbot-rudder
Now you can upload random pictures like this into a separate folder

Sources

 
Copyright © Twig's Tech Tips
Theme by BloggerThemes & TopWPThemes Sponsored by iBlogtoBlog