Search code examples
pythondjangodjango-storagebackblaze

Use Backblaze B2 as Django Default Storage


I want to use Backblaze B2 to serve media files only in Django. I have used django-storages for that purpose, and as per it's documentation it support Backblaze B2.

I used the below configuration in settings.py -

INSTALLED_APPS = [
    ............
    'storages',
    'boto',
]

STORAGES = {
    "default": {
        "BACKEND": "storages.backends.s3boto3.S3Boto3Storage",
    },
    "staticfiles": {
        "BACKEND": "whitenoise.storage.CompressedManifestStaticFilesStorage",
    },
}

AWS_ACCESS_KEY_ID = "<my_backblaze_application_keyID>"
AWS_SECRET_ACCESS_KEY = "<my_backblaze_applicationKey>"
AWS_STORAGE_BUCKET_NAME = "<my_public_bucket_name>"
AWS_S3_REGION_NAME = "<region_set_by_backblaze>"
AWS_S3_ENDPOINT = f"s3.{AWS_S3_REGION_NAME}.backblazeb2.com"
AWS_S3_ENDPOINT_URL = f"https://{AWS_S3_ENDPOINT}"
AWS_S3_CUSTOM_DOMAIN = f'{AWS_STORAGE_BUCKET_NAME}.{AWS_S3_ENDPOINT}'

MEDIA_URL = '/media/'

But the files are not uploading in the Backblaze. How to implement that properly?


Solution

  • You mentioned in a comment that it silently fails, but it saves the data? Does it save the uploaded file to disk also? If so, it sounds like it's still using the default storage backend.

    I just spun up a Django app to test this, as I've had it working in the past, but not since Django 4.2 changed storage configuration. These are the settings that worked for me.

    settings.py

    STORAGES = {
        "default": {
            "BACKEND": "storages.backends.s3boto3.S3Boto3Storage"
        },
        "staticfiles": {
            "BACKEND": "django.contrib.staticfiles.storage.StaticFilesStorage"
        }
    }
    
    AWS_ACCESS_KEY_ID = os.environ['B2_APPLICATION_KEY_ID']
    AWS_SECRET_ACCESS_KEY = os.environ['B2_APPLICATION_KEY']
    AWS_STORAGE_BUCKET_NAME = os.environ['B2_BUCKET_NAME']
    AWS_S3_REGION_NAME = os.environ['B2_REGION']
    AWS_S3_ENDPOINT = f's3.{AWS_S3_REGION_NAME}.backblazeb2.com'
    AWS_S3_ENDPOINT_URL = f'https://{AWS_S3_ENDPOINT}'
    AWS_DEFAULT_ACL = 'public-read'
    
    AWS_LOCATION = 'media/'
    

    Notes on the settings:

    • I didn't need to add anything to INSTALLED_APPS
    • I used the default static storage backend, since I was focused on the Backblaze B2 configuration
    • I'm in the habit of setting credentials as environment variables, to reduce the chance they leak when I push code to GitHub, StackOverflow etc.
    • AWS_S3_REGION_NAME should be us-west-004, eu-central-003 or similar
    • It looks like you're using a public bucket. By default, the S3 backend creates files with a private ACL, but B2 sets visibility at the bucket level, and object ACL's have to match.
    • To put files in a particular folder in the bucket, you need to use AWS_LOCATION, rather than MEDIA_URL. Note that you don't need the leading / in the location.

    I put the entire sample online at https://github.com/backblaze-b2-samples/django-42-example, so you can see how I set up the model, view etc.

    One final thought - check your Django version:

    % python -m django --version 
    4.2.1
    

    If you're using a version older than Django 4.2, the syntax for storage settings is different. You'll need to change this:

    STORAGES = {
        "default": {
            "BACKEND": "storages.backends.s3boto3.S3Boto3Storage",
        },
        "staticfiles": {
            "BACKEND": "whitenoise.storage.CompressedManifestStaticFilesStorage",
        },
    }
    

    to this:

    DEFAULT_FILE_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage'
    
    STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage'