Different storage backend in testing mode and S3 in production mode

Issue #136 wontfix
AhmedR created an issue

In my case, I need to specify a bucket name in the model image field like:

profile_pic = models.ImageField(upload_to=UPLOAD_PATH, null=True, blank=True, storage=S3BotoStorage(bucket=PROFILE_IMGS_BUCKET))

I need to use the Django default storage backend in the testing mode, I tried to omit the option storage=S3BotoStorage(bucket=PROFILE_IMGS_BUCKET) and since my is imported only in the production mode:

if not DEBUG:
DEFAULT_FILE_STORAGE = 'storages.backends.s3boto.S3BotoStorage'

It works!, but the problem is that image is uploaded to the default bucket "AWS_STORAGE_BUCKET_NAME" and I need to specify the bucket name here. The ugly solution is to modify the model code to be aware of the testing mode like this:

if not TESTING:
    profile_pic = models.ImageField(upload_to=UPLOAD_PATH,   storage=S3BotoStorage(bucket=PROFILE_IMGS_BUCKET))
    profile_pic = models.ImageField(upload_to=UPLOAD_PATH)

Do you have any other best practice for this case?


My Proposal is to define a storage backend factory like this:


TESTING = sys.argv[1:2] == ['test']
PROFILE_IMGS_BUCKET = 'xyz-profile-images'
PRODUCT_IMGS_BUCKET = 'xyz-product-images'


from storages.backends.s3boto import S3BotoStorage

def get_profile_storage_backend():
    if TESTING:
        return None
        return S3BotoStorage(bucket=PROFILE_IMGS_BUCKET)

def get_product_storage_backend():
    if TESTING:
        return None
        return S3BotoStorage(bucket=PRODUCT_IMGS_BUCKET)


   profile_pic = models.ImageField(storage=get_profile_storage_backend())
   image = models.ImageField(storage=get_product_storage_backend())

Comments (6)

  1. Ian Lewis

    If you would like to have a different backend in production and testing you can simply create two settings.py files for each environment and specify the settings module path using the --settings option to manage.py

    If your settings files were settings_testing.py and settings_production.py you would use them as follows:

    python manage.py runserver --settings=settings_testing

  2. AhmedR reporter

    Thanks Ian,

    I already have 2 different settings files for production and testings. The problem is the only way to specify the bucket name is by parametrizing the storage passed the ImageField object not in the settings.

  3. Richard Leland

    @montaro thanks for submitting this ticket. I feel like this is a very specific use-case to your application and you've resolved it elegantly! In most user cases there are two buckets total - one for media and one for static. I'd say in 99% of cases people are simply using the upload_to argument to specify where items live within a bucket.

    In your case you want to change the buckets for individual file fields. While I understand your use, I do think it's something that is not common and should be implemented on the application side, not in django-storages.

    I'm going to mark this as wontfix, but know that I'll keep an eye on any other similar use cases and appreciate the discussion! It's really helpful for us to understand how everyone is using django-storages.

  4. Log in to comment