Comments on: Uploading images to a dynamic path with Django http://scottbarnham.com/blog/2007/07/31/uploading-images-to-a-dynamic-path-with-django/ Code and comments on web development, Django, Python and things (un)related. Wed, 03 Apr 2013 13:15:20 +0000 hourly 1 http://wordpress.org/?v=4.3 By: Scott http://scottbarnham.com/blog/2007/07/31/uploading-images-to-a-dynamic-path-with-django/comment-page-1/#comment-776 Thu, 04 Mar 2010 16:35:08 +0000 http://scottbarnham.com/blog/2007/07/31/uploading-images-to-a-dynamic-path-with-django/#comment-776 Thanks Mishu, but there’s a newer official way to do this in Django.

See:
http://scottbarnham.com/blog/2008/08/25/dynamic-upload-paths-in-django/

]]>
By: Mishu http://scottbarnham.com/blog/2007/07/31/uploading-images-to-a-dynamic-path-with-django/comment-page-1/#comment-775 Wed, 03 Mar 2010 12:25:23 +0000 http://scottbarnham.com/blog/2007/07/31/uploading-images-to-a-dynamic-path-with-django/#comment-775 Here is the updated version that works with latest Django:

from django.db.models import ImageField, signals


class CustomImageField(ImageField):
    """Allows model instance to specify upload_to dynamically.

    Model class should have a method like:

        def get_upload_to(self, attname):
            return 'path/to/%d' % self.id

    Based on: http://code.djangoproject.com/wiki/CustomUploadAndFilters
    """
    def __init__(self, *args, **kwargs):
        if not 'upload_to' in kwargs:
            kwargs['upload_to'] = 'dummy'
        self.prime_upload = kwargs.get('prime_upload', False)
        if 'prime_upload' in kwargs:
            del(kwargs['prime_upload'])
        super(CustomImageField, self).__init__(*args, **kwargs)

    def contribute_to_class(self, cls, name, **kwargs): 
        """Hook up events so we can access the instance."""
        super(CustomImageField, self).contribute_to_class(cls, name)
        if self.prime_upload:
            signals.post_init.connect(self._get_upload_to, sender=cls)
        signals.pre_save.connect(self._get_upload_to, sender=cls)

    def _get_upload_to(self, instance=None, **kwargs):
        """Get dynamic upload_to value from the model instance."""
        if hasattr(instance, 'get_upload_to'):
            self.upload_to = instance.get_upload_to(self.attname)

    def db_type(self):
        """Required by Django for ORM."""
        return 'varchar(100)'
]]>
By: Scott http://scottbarnham.com/blog/2007/07/31/uploading-images-to-a-dynamic-path-with-django/comment-page-1/#comment-301 Mon, 25 Aug 2008 21:48:30 +0000 http://scottbarnham.com/blog/2007/07/31/uploading-images-to-a-dynamic-path-with-django/#comment-301 @Fidel Ramos

I have a new short post with an example of how to get dynamic upload paths since the FileStorageRefactor merge. It uses a callable in the upload_to parameter and is much simpler than the method in this post.

See:
Dynamic upload paths in Django

]]>
By: Fidel Ramos http://scottbarnham.com/blog/2007/07/31/uploading-images-to-a-dynamic-path-with-django/comment-page-1/#comment-292 Thu, 21 Aug 2008 11:23:02 +0000 http://scottbarnham.com/blog/2007/07/31/uploading-images-to-a-dynamic-path-with-django/#comment-292 This solution was working fine until the File Storage refactoring (http://code.djangoproject.com/wiki/FileStorageRefactor), and I’m afraid the changes to make it work again may be extensive. Anyone knows a File Storage-compatible substitute?

]]>
By: mat http://scottbarnham.com/blog/2007/07/31/uploading-images-to-a-dynamic-path-with-django/comment-page-1/#comment-288 Fri, 08 Aug 2008 10:04:19 +0000 http://scottbarnham.com/blog/2007/07/31/uploading-images-to-a-dynamic-path-with-django/#comment-288 Because of http://code.djangoproject.com/wiki/BackwardsIncompatibleChanges#Signalrefactoring I guess this is gonna look like this:

def contribute_to_class(self, cls, name):
“””
Hook up events so we can access the instance.
“””
super(CustomImageField, self).contribute_to_class(cls, name)
if self.prime_upload:
signals.post_init.connect(self._get_upload_to, sender=cls)
signals.pre_save.connect(self._get_upload_to, sender=cls)

def _get_upload_to(self, **kwargs):
“””
Get dynamic upload_to value from the model instance.
“””
instance = kwargs[‘instance’]
if hasattr(instance, ‘get_upload_to’):
self.upload_to = instance.get_upload_to(self.attname)

]]>
By: Ben http://scottbarnham.com/blog/2007/07/31/uploading-images-to-a-dynamic-path-with-django/comment-page-1/#comment-287 Wed, 06 Aug 2008 04:02:12 +0000 http://scottbarnham.com/blog/2007/07/31/uploading-images-to-a-dynamic-path-with-django/#comment-287 In an effort to get this going with newforms-admin I tried working with the post_save signal. I’ve posted it on my blog:
http://pandemoniumillusion.wordpress.com/2008/08/06/django-imagefield-and-filefield-dynamic-upload-path-in-newforms-admin/

]]>
By: Ben http://scottbarnham.com/blog/2007/07/31/uploading-images-to-a-dynamic-path-with-django/comment-page-1/#comment-284 Tue, 05 Aug 2008 02:38:45 +0000 http://scottbarnham.com/blog/2007/07/31/uploading-images-to-a-dynamic-path-with-django/#comment-284 Great Post! I’ve used this for a while now.
However, this seems to have broken with the inclusion of the Newforms Admin now. I’m getting a DoesNotExist error on the instance. Have you tried the newest revision?

]]>
By: Scott http://scottbarnham.com/blog/2007/07/31/uploading-images-to-a-dynamic-path-with-django/comment-page-1/#comment-205 Tue, 20 May 2008 12:02:51 +0000 http://scottbarnham.com/blog/2007/07/31/uploading-images-to-a-dynamic-path-with-django/#comment-205 @Michael

I’ve just posted an updated version (see above) which should work in this situation.

]]>
By: Michael http://scottbarnham.com/blog/2007/07/31/uploading-images-to-a-dynamic-path-with-django/comment-page-1/#comment-204 Tue, 20 May 2008 04:55:40 +0000 http://scottbarnham.com/blog/2007/07/31/uploading-images-to-a-dynamic-path-with-django/#comment-204 The CustomImageField class doesn’t properly save the image to the specified dynamic path via the following code:

if form.is_valid():
l = ListingImage()

uploadedImage = form.cleaned_data[‘image’] # an UploadedFile object
l.save_image_file(uploadedImage.filename, uploadedImage.content)

l.caption = form.cleaned_data[‘caption’]
l.sort = form.cleaned_data[‘sort’]
l.save()

ListingImage.image is a CustomImageField()

Anyone know why calling save_image_file() doesn’t invoke the get_upload_to() to save the image to the dynamic path?

]]>
By: Scott http://scottbarnham.com/blog/2007/07/31/uploading-images-to-a-dynamic-path-with-django/comment-page-1/#comment-199 Fri, 02 May 2008 07:40:06 +0000 http://scottbarnham.com/blog/2007/07/31/uploading-images-to-a-dynamic-path-with-django/#comment-199 Hi Chris.

Yes, you can. The model that contains the CustomImageField gets to build up the path. Assuming you have a Photo model which has a CustomImageField and is related to a user, you could do something like:

class Photo(models.Model):
    user = models.ForeignKey(User, related_name='photos')
    image = CustomImageField(upload_to='photos')
    creation_date = models.DateTimeField()
    ...
    
    def get_upload_to(self, field_attname):
        return self.user.username

The upload path will be made up of the media path, username and filename. Assuming the username is “ted”, you will get something like: /path/to/media/ted/head.jpg

]]>