---
name: storages
description: "django-storages package guide for Django file and static storage backends"
metadata:
  languages: "python"
  versions: "1.14.6"
  revision: 2
  updated-on: "2026-03-12"
  source: maintainer
  tags: "django-storages,django,storage,s3,azure,gcs,staticfiles"
---

# django-storages Python Package Guide

## What It Is

`django-storages` plugs cloud and remote storage backends into Django's storage API.

- Package name: `django-storages`
- Django app: `storages`
- Import path you usually configure: backend class string in Django settings
- Version covered: `1.14.6`

Most projects do not call `django-storages` APIs directly. You configure a backend, then keep using Django's normal file APIs such as `default_storage`, `FileField`, `ImageField`, and `collectstatic`.

## Install

Install the package version your project is pinned to:

```bash
pip install django-storages==1.14.6
```

Add the app:

```python
INSTALLED_APPS = [
    # ...
    "storages",
]
```

You also need the provider SDK for the backend you choose. Typical combinations are:

- Amazon S3: `boto3`
- Azure Blob Storage: `azure-storage-blob`
- Google Cloud Storage: `google-cloud-storage`

Examples:

```bash
pip install django-storages==1.14.6 boto3
pip install django-storages==1.14.6 azure-storage-blob
pip install django-storages==1.14.6 google-cloud-storage
```

## Initialization And Setup

### Django 4.2 And Newer

Use Django's `STORAGES` setting. This is the upstream-recommended pattern for `django-storages` because it lets you configure separate storage instances without subclassing.

Example with different S3 prefixes for media and static files:

```python
STORAGES = {
    "default": {
        "BACKEND": "storages.backends.s3.S3Storage",
        "OPTIONS": {
            "bucket_name": "my-app-bucket",
            "region_name": "us-east-1",
            "default_acl": None,
            "location": "media",
            "file_overwrite": False,
        },
    },
    "staticfiles": {
        "BACKEND": "storages.backends.s3.S3Storage",
        "OPTIONS": {
            "bucket_name": "my-app-bucket",
            "region_name": "us-east-1",
            "default_acl": None,
            "location": "static",
        },
    },
}
```

### Django Earlier Than 4.2

Legacy global settings still work for older Django versions:

```python
DEFAULT_FILE_STORAGE = "storages.backends.s3.S3Storage"
STATICFILES_STORAGE = "storages.backends.s3.S3Storage"

AWS_STORAGE_BUCKET_NAME = "my-app-bucket"
AWS_S3_REGION_NAME = "us-east-1"
AWS_DEFAULT_ACL = None
AWS_LOCATION = "media"
```

If you need two differently configured storages before Django 4.2, the upstream docs call out subclassing as the usual workaround.

## Core Usage

Once configured, use Django's normal storage API.

Save a generated file:

```python
from django.core.files.base import ContentFile
from django.core.files.storage import default_storage

name = default_storage.save(
    "uploads/report.txt",
    ContentFile(b"generated by django-storages"),
)

public_url = default_storage.url(name)
```

Model-backed uploads work the same way:

```python
from django.db import models

class Document(models.Model):
    file = models.FileField(upload_to="documents/")
```

If your `default` storage alias points at a `django-storages` backend, Django routes reads and writes through that backend automatically.

## Backend Setup Patterns

### Amazon S3

For `1.14.6`, prefer the current backend path used in the official docs:

```python
"storages.backends.s3.S3Storage"
```

Minimal Django 4.2+ media storage:

```python
STORAGES = {
    "default": {
        "BACKEND": "storages.backends.s3.S3Storage",
        "OPTIONS": {
            "bucket_name": "my-app-bucket",
            "region_name": "us-east-1",
            "default_acl": None,
            "querystring_auth": True,
            "object_parameters": {
                "CacheControl": "max-age=86400",
            },
        },
    },
}
```

Credential resolution in the official S3 docs is, in order:

1. `session_profile`
2. Explicit backend options such as `access_key`, `secret_key`, and `security_token`
3. S3-specific environment variables
4. Generic AWS environment variables

Practical guidance:

- Prefer environment variables, IAM roles, or another boto3-supported credential chain.
- Use `location` to separate static and media prefixes.
- Use `object_parameters` for headers such as `CacheControl`, `SSEKMSKeyId`, `StorageClass`, and `Tagging`.
- Set `file_overwrite` explicitly if you do not want later uploads to replace files with the same name.
- If you point at an S3-compatible service, set `endpoint_url` and keep `region_name` aligned so signed URLs keep working.

### Azure Blob Storage

Backend path:

```python
"storages.backends.azure_storage.AzureStorage"
```

Minimal setup:

```python
STORAGES = {
    "default": {
        "BACKEND": "storages.backends.azure_storage.AzureStorage",
        "OPTIONS": {
            "account_name": "myaccount",
            "account_key": "...",
            "azure_container": "media",
        },
    },
}
```

Common auth and config patterns from the official docs:

- `account_name` plus `account_key`
- `connection_string`
- `token_credential` for Azure Identity based auth
- `azure_container` for the target container
- `expiration_secs` to control signed URL lifetime

Use a pre-created container and keep secrets out of committed settings files.

### Google Cloud Storage

Backend path:

```python
"storages.backends.gcloud.GoogleCloudStorage"
```

Minimal setup:

```python
STORAGES = {
    "default": {
        "BACKEND": "storages.backends.gcloud.GoogleCloudStorage",
        "OPTIONS": {
            "bucket_name": "my-gcs-bucket",
            "project_id": "my-project-id",
        },
    },
}
```

Practical auth and URL notes:

- The backend can use default Google application credentials or explicit credentials.
- `default_acl` affects whether uploaded objects are private or public by default.
- `querystring_auth` controls whether generated URLs are signed.
- `iam_sign_blob` is available in `1.14.6` when you need signed URLs without a local private key.

If you use uniform bucket-level access, avoid patterns that depend on per-object ACLs.

## Static Files

For Django 4.2+, use a dedicated `staticfiles` alias:

```python
STORAGES = {
    "staticfiles": {
        "BACKEND": "storages.backends.s3.S3Storage",
        "OPTIONS": {
            "bucket_name": "my-app-bucket",
            "location": "static",
            "default_acl": None,
        },
    },
}
```

Then run:

```bash
python manage.py collectstatic
```

Keep static and media files in different prefixes or different buckets/containers so `collectstatic` does not mix with user uploads.

## Config And Auth Notes

- Add `"storages"` to `INSTALLED_APPS`.
- Prefer `STORAGES` on Django 4.2+.
- Keep credentials in environment variables, cloud-native credential chains, or secret managers.
- Separate `default` and `staticfiles` config.
- Use backend options in `STORAGES["..."]["OPTIONS"]`; do not mix old global settings into a partial 4.2 migration.
- Validate generated URLs in tests when you change `custom_domain`, `querystring_auth`, `endpoint_url`, or signed URL expiration settings.

## Common Pitfalls

### Copying Old S3 Import Paths

Older examples still use `storages.backends.s3boto3.S3Boto3Storage`.

For `1.14.6`, prefer:

```python
"storages.backends.s3.S3Storage"
```

### Mixing Django 4.2 `STORAGES` With Legacy Global Settings

Do not do a half-migration. Pick one configuration style that matches your Django version.

### Reusing The Same Prefix For Static And Media Files

If both aliases point to the same bucket and `location`, user uploads and `collectstatic` output can overwrite or clutter each other.

### Assuming `default_acl` Overrides Everything

For S3, the docs note that `default_acl` is ignored if you set `ACL` inside `object_parameters`.

### Hardcoding Cloud Credentials

Hardcoded credentials in Django settings are easy to leak and harder to rotate. All three major backends documented here support better environment-based or provider-native auth flows.

### Misconfiguring Public URLs

- On S3, `custom_domain` and `STATIC_URL` slash handling can produce broken URLs if you mix trailing slash assumptions.
- On GCS, public URLs depend on ACL configuration and signing settings.
- On Azure, signed URL behavior depends on your credential mode and expiration configuration.

## Version-Sensitive Notes

- This doc is for `django-storages` `1.14.6`.
- The docs URL uses `/en/latest/`, and as of 2026-03-12 the latest docs and PyPI package page both match `1.14.6`, so there was no version drift on that date.
- The 1.14-series docs use `storages.backends.s3.S3Storage`; older `s3boto3` snippets from blog posts are stale for current projects.
- `1.14.6` adds Google Cloud Storage IAM Sign Blob support and includes S3-related fixes noted in the upstream changelog.
- If you are debugging older code written before the 1.14 migration work, verify backend class paths and storage settings before changing application code.

## Official Sources

- Versioned docs root: https://django-storages.readthedocs.io/en/1.14.6/
- Latest docs root: https://django-storages.readthedocs.io/en/latest/
- Amazon S3 backend docs: https://django-storages.readthedocs.io/en/1.14.6/backends/amazon-S3.html
- Azure backend docs: https://django-storages.readthedocs.io/en/1.14.6/backends/azure.html
- Google Cloud Storage backend docs: https://django-storages.readthedocs.io/en/1.14.6/backends/gcloud.html
- PyPI registry page: https://pypi.org/project/django-storages/
- PyPI JSON metadata: https://pypi.org/pypi/django-storages/json
- Upstream changelog: https://github.com/jschneier/django-storages/blob/master/CHANGELOG.rst
