proper way to use S3Storage and Django ImageField

1,869 views
Skip to first unread message

Aaron Lee

unread,
Jan 12, 2009, 12:53:27 PM1/12/09
to django...@googlegroups.com, lar...@gmail.com
Hi all and David,

installation and created a simple model

class Avatar(models.Model):
    """
    Avatar model
    """
    image = models.ImageField(upload_to="userprofile")
    user = models.ForeignKey(User)

By using the upload_to="userprofile" (which is also the example given on the django-s3-storage.html) 
the path would be something like userprofile/my.jpg
which would trigger the file storage backend exception

File "/usr/local/src/djtrunk.latest/django/core/files/storage.py", line 81, in path
raise NotImplementedError("This backend doesn't support absolute paths.")
where name is userprofile/my.jpg

What's the recommended way of using S3 with ImageField?

-Aaron

Aaron

unread,
Jan 15, 2009, 1:30:00 PM1/15/09
to Django users
ping?

On Jan 12, 9:53 am, "Aaron Lee" <waifun...@gmail.com> wrote:
> Hi all and David,
>
> I followed thehttp://code.larlet.fr/doc/django-s3-storage.html

Aaron Lee

unread,
Jan 19, 2009, 11:02:52 AM1/19/09
to Django users
So I guess S3Storage doesn't work with ImageField? Can anyone confirm that?

-Aaron

creecode

unread,
Jan 19, 2009, 3:40:17 PM1/19/09
to Django users
Hello Aaron,

I can confirm that it can work. I'm using it but I don't know enough
to diagnose your problem.

Have you created the userprofile "directory" in your S3 bucket?

Have you added the following to your settings.py?

DEFAULT_FILE_STORAGE = 'S3Storage.S3Storage'

AWS_ACCESS_KEY_ID
AWS_SECRET_ACCESS_KEY
AWS_STORAGE_BUCKET_NAME
AWS_CALLING_FORMAT

Have you installed any software S3Storage depends on?

On Jan 19, 8:02 am, "Aaron Lee" <waifun...@gmail.com> wrote:
> So I guess S3Storage doesn't work with ImageField? Can anyone confirm that?

Toodle-loooooooooooo.............
creecode

Merrick

unread,
Jan 19, 2009, 4:22:04 PM1/19/09
to Django users
I am using S3Storage with an imagefield successfully. It sounds like
you have not specified the storage engine and keys etc... in
settings.py as creecode pointed out.

I recall testing that the directory will be created on the fly if it
does not exist.

Aaron Lee

unread,
Jan 19, 2009, 4:53:53 PM1/19/09
to django...@googlegroups.com
Yes and yes,
here are my settings in settings.py

# Storage Settings
DEFAULT_FILE_STORAGE = 'libs.storages.S3Storage.S3Storage'
AWS_ACCESS_KEY_ID='xxx'
AWS_SECRET_ACCESS_KEY='xxx'
AWS_STORAGE_BUCKET_NAME='userprofile'
from S3 import CallingFormat
AWS_CALLING_FORMAT=CallingFormat.SUBDOMAIN
AWS_HEADERS = {
    'Expires': 'Sat, 10 Jan 2049 00:00:00 GMT',
    'Cache-Control': 'max-age=86400',
    }
#

and I also verified that I have a bucket called "userprofile" in my Amazon account.
In the DB I have
mysql> select * from userprofile_avatar;
+----+---------------------+---------+---------------------+-------+
| id | image               | user_id | date                | valid |
+----+---------------------+---------+---------------------+-------+
|  4 | userprofile/cs1.jpg |       2 | 2009-01-19 13:46:12 |     0 |
+----+---------------------+---------+---------------------+-------+

But I am still getting the exception saying the backend doesn't support absolute paths.
In django/db/models/fields/files.py line 52 _get_path
  return self.storage.path(self.name)

and my self.name is userprofile/cs1.jpg

Any suggestions?
-Aaron

creecode

unread,
Jan 19, 2009, 6:11:47 PM1/19/09
to Django users
Hey Aaron,

I think part of your problem is that AWS_STORAGE_BUCKET_NAME is not
properly specified. It think it needs to be something like my-bucket-
name.s3.amazonaws.com. Based on your settings then you should find
your images end up at http:my-bucket-name.s3.amazonaws.com/
userprofile/. You may need to change the permissions on your bucket
and "directories" so that you can access the images via a url. I
found S3 Organizer a plug-in for FireFox useful for this.

Toodle-loooooooo............
creecode

On Jan 19, 1:53 pm, "Aaron Lee" <waifun...@gmail.com> wrote:

> AWS_STORAGE_BUCKET_NAME='userprofile'

Aaron Lee

unread,
Jan 19, 2009, 7:01:22 PM1/19/09
to django...@googlegroups.com
Thanks for your tip, I believe your suggestion will end up having my.jpg under
my-bucket-name.s3.amazonaws.com.s3.amazonaws.com/userprofile/my.jpg

I think the AWS_STORAGE_BUCKET_NAME should just be userprofile

With your tip I think I narrow down the issue. The old way of the image being accessed was

image = Image.open(avatar.image.path)

But S3Storage doesn't define the _path function and hence the absolute path exception.
Not sure why S3StorageFile doesn't have the path() function either.
 
So how do you access the image, do you manually construct the URL?

-Aaron

David Larlet

unread,
Jan 19, 2009, 7:02:58 PM1/19/09
to django...@googlegroups.com

Le 19 janv. 09 à 22:53, Aaron Lee a écrit :

>
> But I am still getting the exception saying the backend doesn't
> support absolute paths.
> In django/db/models/fields/files.py line 52 _get_path
> return self.storage.path(self.name)
>
> and my self.name is userprofile/cs1.jpg
>
> Any suggestions?

Hi Aaron,

Sorry for my late answer, I was on holidays, what about
instance.url()? (that's the recommended way to do, .path() is for
local storages)

Regards,
David


Aaron Lee

unread,
Jan 19, 2009, 7:48:34 PM1/19/09
to django...@googlegroups.com
Thanks David, but it seems awkward to call

avatar.image.storage.url(str(avatar.image))

to retrieve the URL for an ImageField.
Do you have a better way?

-Aaron

David Larlet

unread,
Jan 19, 2009, 7:54:18 PM1/19/09
to django...@googlegroups.com

Le 20 janv. 09 à 01:48, Aaron Lee a écrit :

> Thanks David, but it seems awkward to call
>
> avatar.image.storage.url(str(avatar.image))
>
> to retrieve the URL for an ImageField.
> Do you have a better way?

avatar.image.url should work (without parenthesis, that's a property).
I propose to continue the discussion as private, I don't want to flood
that list with custom apps.

David

PS: note to self, add more examples in documentation...

Message has been deleted

Aaron Lee

unread,
Jan 19, 2009, 10:03:44 PM1/19/09
to django...@googlegroups.com
Yes avatar.image.url works, thanks again. -Aaron

On Mon, Jan 19, 2009 at 5:17 PM, creecode <cree...@gmail.com> wrote:

I think you may be correct on that my tip was incorrect.  Forget what
I said! :-)

Have you tried getting the url like avatar.image.url?  I use a line
like this in some of my code that uses S3Storage and it works.

image_url = my_model_instance.image.url.replace ( ':80', '' )


On Jan 19, 4:01 pm, "Aaron Lee" <waifun...@gmail.com> wrote:
> Thanks for your tip, I believe your suggestion will end up having my.jpg
> under
> my-bucket-name.s3.amazonaws.com.s3.amazonaws.com/userprofile/my.jpg
>
> I think the AWS_STORAGE_BUCKET_NAME should just be userprofile

Reply all
Reply to author
Forward
0 new messages