> ## Documentation Index
> Fetch the complete documentation index at: https://docs.sevalla.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Django - Object storage

> The guide explains how to set up object storage for your Django application.

If your application supports user-uploaded files (such as media uploads), you’ll need a storage solution separate from the application’s local filesystem. [Sevalla’s object storage](https://docs.sevalla.com/object-storage/overview) is ideal for securely storing and serving these files. Static files can also be delivered from object storage if desired, though this is optional and depends on your application’s setup and performance needs.

## Media Files

Start by [creating an object storage](https://docs.sevalla.com/object-storage/add-an-object-storage) on Sevalla. **Settings** contains all the values needed for your storages settings.

### Install

Before your media files can be uploaded to object storage, the `django-storages` library must be added to your dependencies. Sevalla's object storage is S3-compatible, so the s3 extra should be included when installing, which installs boto3 for you.

```shellsession theme={null}
pip install django-storages[s3]
pip freeze > requirements.txt
```

### Settings

You need to add the storages settings to `settings.py`. Both the signature version of `s3v4` and the `storages.backends.s3.S3Storage` are necessary for Django to properly use the object storage.

You can use your preferred method for defining configuration values for `access_key`, `secret_key`, `bucket_name`, and `endpoint_url`. django-environ is used for this example.

```python theme={null}
STORAGES = { # [!code ++:12]
    "default": {
        "BACKEND": "storages.backends.s3.S3Storage",
        "OPTIONS": {
            "access_key": env("MEDIA_BUCKET_ACCESS_KEY"),
            "secret_key": env("MEDIA_BUCKET_SECRET_KEY"),
            "bucket_name": env("MEDIA_BUCKET_NAME"),
            "endpoint_url": env("MEDIA_BUCKET_ENDPOINT_URL"),
            "signature_version": "s3v4"
        }
    }
}
```

If you would like your media bucket to be publicly accessible, in the object storage **Settings**, click **Enable public access**.

Then you'll need to add the `custom_domain` to your storages settings dictionary.

```python theme={null}
STORAGES = { #
    "default": {
        "BACKEND": "storages.backends.s3.S3Storage",
        "OPTIONS": {
            "access_key": env("MEDIA_BUCKET_ACCESS_KEY"),
            "secret_key": env("MEDIA_BUCKET_SECRET_KEY"),
            "bucket_name": env("MEDIA_BUCKET_NAME"),
            "endpoint_url": env("MEDIA_BUCKET_ENDPOINT_URL"),
            "custom_domain": env("MEDIA_BUCKET_DOMAIN"), # [!code ++]
            "signature_version": "s3v4"
        }
    }
}
```

Once your app is restarted with the configuration values loaded, it will place any user-uploaded files into object storage instead of the file system.

## Static Files

Static files can also be placed in an object storage instead of being served directly from your app with WhiteNoise. If you will have both media files and static files served from an object store, you should use a separate object storage for each type.

Start by [creating a new object storage](https://docs.sevalla.com/object-storage/add-an-object-storage) on Sevalla. To fully support all the static files used for the admin dashboard, you should make your static file object store public.

### Settings

Add separate settings for `staticfiles` in the `STORAGES` dictionary.

```python theme={null}
STORAGES = {
    "default": {
        "BACKEND": "storages.backends.s3.S3Storage",
        "OPTIONS": {
            "access_key": env("MEDIA_BUCKET_ACCESS_KEY"),
            "secret_key": env("MEDIA_BUCKET_SECRET_KEY"),
            "bucket_name": env("MEDIA_BUCKET_NAME"),
            "endpoint_url": env("MEDIA_BUCKET_ENDPOINT_URL"),
            "signature_version": "s3v4"
        }
    },
    "staticfiles": { # [!code ++:11]
        "BACKEND": "storages.backends.s3.S3Storage",
        "OPTIONS": {
            "access_key": env("STATIC_BUCKET_ACCESS_KEY"),
            "secret_key": env("STATIC_BUCKET_SECRET_KEY"),
            "bucket_name": env("STATIC_BUCKET_NAME"),
            "endpoint_url": env("STATIC_BUCKET_ENDPOINT_URL"),
            "custom_domain": env("STATIC_BUCKET_DOMAIN"),
            "signature_version": "s3v4"
        }
    }
}
```

Django doesn't use the `STATIC_URL` setting when `STORAGES` is set but still requires it, so for clarity, you may want to add the proper `STATIC_URL` to `settings.py` .

```python theme={null}
STATIC_URL = 'static/' # [!code --]
STATIC_URL = f'{env("STATIC_BUCKET_DOMAIN")}/' # [!code ++]
```

You can then remove WhiteNoise, if you have it.

```python theme={null}
MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware', 
    'whitenoise.middleware.WhiteNoiseMiddleware', # [!code --]
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
```

Your static files will now be uploaded to the bucket when the collectstatic command is run.

<Info>
  The collectstatic command will take longer to run because the static files need to be uploaded to the object storage.
</Info>
