Solving django-storage NotImplementedError with Amazon S3

Recently I started looking into Amazon’s S3 service to (hopefully) offer better performance on serving up static content for our customers.  Its a great service and ridiculously cheap.  The first client I am applying the S3 storage to is for Dylan Priest Photography, its critical that the images load as fast as possible as that is the main content of his site.  As our web-server is currently a bit overworked off loading the static content to S3 should help with overall performance.

Here at Hardly Code, we are mostly a Django shop.  I found a great plugin called django-storages that has multiple different type of storages.  The documentation is a little bit on the lite side and took a few hours to get the feel for it.  (It was my first time not using the default storage.)

I was applying this to our Album app but when trying to edit an album I kept getting (Creating a new album worked fine):
NotImplementedError: This backend doesn't support absolute paths.
The conflict was in the s3boto storage class the path method was not implemented. As per the Django documentation, for non local storage you should not implement this method.  The only way I found to solve this solution was to go ahead and implement this method in the django-storage code and modify storages.backends.s3boto and add the path method.


def url(self, name):
...
def path(self, name):
return None

A fairly easy fix and as far as I can tell it hasn’t created any issues with the modification. Not sure if this a bug with django, django-storage, or my implementation, but it took me long enough to figure out that I thought I would document it and hopefully save someone else some time.

8 Responses to Solving django-storage NotImplementedError with Amazon S3

  1. Greg says:

    There’s good reason why the django docs say not to do this… the path method is for when you want an absolute local path to the file; I can’t see how returning None in that method could possibly be good.

  2. Woot! Thanks for figuring this out. So to be sure, you added the path method right after the url method, yeah?

  3. I added what you suggested and still get an error when running collectstatic… traceback is here. http://pastie.org/3825411 Mind looking at it? :)

  4. Ragnarok says:

    After I add this method, Django raise another error: AttributeError
    ‘NoneType’ object has no attribute ‘rfind’

  5. Murph Murphy says:

    Hey, just wanted to let everyone know how I got this working (without going against Django principles). Using .url or .name instead didn’t work, but S3Storage has a solution built in.

    Instead of:
    photo = Image.open(self.image.path)

    Use:
    from django.core.files.storage import default_storage as storage
    photo = Image.open(storage.open(self.image.name))

    Worked like a charm!

  6. Wil Black says:

    @Murph Murphy. I am having this exact problem, you post says you fixed it in a Dajngo way. Where exactly did you put those lines of code. I would love to get this working. I am rehosting an old site onto dotCloud and need a remote storage solution for uploaded photos.

    Here is a snippet of code from my upload view:

    uploaded_file = request.FILES['filedata']

    photo = UserPhoto() # <– Photologue ImageModel
    photo.user=profile.user

    # Breaks here with the NotImplemented Error
    photo.image.save(uploaded_file.name, uploaded_file)

    photo.save()

    Any advice?

  7. Murph Murphy says:

    @Wil Black: Check out this StackOverflow answer, I think this is what lead me to the solution I had above http://stackoverflow.com/a/14681113/1389855

  8. Igor says:

    This fork of django-photologue works with s3 perfectly:

    https://github.com/petry/django-photologue/

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>