16

In settings.py I have:

STATICFILES_STORAGE = 'storages.backends.s3boto.S3BotoStorage'

DEFAULT_FILE_STORAGE = 'storages.backends.s3boto.S3BotoStorage'
AWS_ACCESS_KEY_ID = 'xxxxxxxxxxxxx'
AWS_SECRET_ACCESS_KEY = 'xxxxxxxxxxxxx'
AWS_STORAGE_BUCKET_NAME = 'static.mysite.com'

This is pointing to my S3 bucket static.mysite.com and works fine when I do manage.py collectstatic, it uploads all the static files to my bucket. However, I have another bucket which I use for different purposes and would like to use in certain areas of the website, for example if I have a model like this:

class Image(models.Model):
    myobject = models.ImageField(upload_to='my/folder')

Now when Image.save() is invoked, it will still upload the file to the S3 bucket in AWS_STORAGE_BUCKET_NAME, however I want this Image.save() to be point to another S3 bucket. Any clean way of doing this? I don't want to change settings.py in run time nor implement any practices that violate the key principles of django, i.e. having a pluggable easy-to-change backend storage.

juliomalegria
  • 24,229
  • 14
  • 73
  • 89
Aziz Alfoudari
  • 5,193
  • 7
  • 37
  • 53

1 Answers1

25

The cleanest way for you would be to create a subclass of S3BotoStorage, and override default bucket name in the init method.

from django.conf import settings
from storages.backends.s3boto import S3BotoStorage

class MyS3Storage(S3BotoStorage):
    def __init__(self, *args, **kwargs):
        kwargs['bucket'] = getattr(settings, 'MY_AWS_STORAGE_BUCKET_NAME')
        super(MyS3Storage, self).__init__(*args, **kwargs)

Then specify this class as your DEFAULT_FILE_STORAGE and leave STATICFILES_STORAGE as it is, or vise versa.

Andrew Kurinnyi
  • 767
  • 6
  • 7
  • Nice! Where do you recommend to place this class in? – Aziz Alfoudari Feb 07 '12 at 10:55
  • Somewhere in your project. I usually have separate app where I keep all project-specific things. – Andrew Kurinnyi Feb 07 '12 at 11:08
  • I created `storages.py` in an app called `core`, how should I refer to `MYS3Storage` in `STATICFILES_STORAGE`? – Aziz Alfoudari Feb 07 '12 at 22:38
  • The same way as if you would import it `core.storages.MYS3Storage` – Andrew Kurinnyi Feb 08 '12 at 04:20
  • Coming back to this question, there is always an error showing up when I do `python manage.py collectstatic`, it says `Error importing storage module core.storage_backends: "No module named backends.s3boto"`. It seems like an issue with the line `from storages.backends.s3boto import S3BotoStorage`. – Aziz Alfoudari Feb 24 '12 at 06:29
  • Solved the above issue, you can read about it [here](http://stackoverflow.com/questions/9430770/django-error-importing-storages-backends) – Aziz Alfoudari Feb 24 '12 at 21:47
  • Couple of notes - the super() call should be to super(MyS3Storage, self).. etc, and I had to change the 'bucket_name' kwarg to 'bucket'. Maybe it's changed? Thanks :) – Rolo Jul 02 '12 at 10:31
  • No need to do this; see the answer at http://stackoverflow.com/questions/10419248/django-storages-with-multiple-s3-buckets for a slightly cleaner resolution. – Tim Smith Dec 19 '12 at 07:21
  • For those needing it, the import fix for django>1.9 is `from storages.backends.s3boto3 import S3Boto3Storage` – artoonie Jul 25 '20 at 06:43