Learn how to migrate your existing Django project utilising django-minio-backend from an older version to the latest release.
Added support for multipart uploads. A fix for Uploading large files consumes a lot of memory #50.
Three new optional parameters have been added to django_minio_backend.models.MinioBackend:
MINIO_MULTIPART_UPLOAD# default: FalseMINIO_MULTIPART_THRESHOLD# default: 10MBMINIO_MULTIPART_PART_SIZE# default: 10MB
See settings.py for a reference implementation.
Django 5.1 introduced a breaking change:
The
DEFAULT_FILE_STORAGEandSTATICFILES_STORAGEsettings have been removed.
Version 4.0.0 of django-minio-backend introduces the following breaking changes to align with this requirement:
- All MinIO configuration parameters must now be wrapped within the
STORAGES["default"]["OPTIONS"]dictionary - Separate control for static files through the
STORAGES["staticfiles"]configuration - Support for multiple MinIO endpoints (optional)
- Settings parameter
MINIO_MEDIA_FILES_BUCKETrenamed toMINIO_DEFAULT_BUCKET - Static file buckets are now forced to be public (Django requirement)
- Model field storage declarations must use lazy-loaded callables (see step 4 below)
MinioBackendclass now requires astorage_nameparameter when instantiated directly- Management command
is_minio_availableupdated to work with the new configuration structure - Improved default setting options for easier configuration
MinioBackend.listdir()has been reimplemented to return a 2-tuple of lists meeting the Django Storage API requirements (fixes issue #59)- Class
DjangoMinioBackendConfigreworked for better validation - Added
utils.get_storages_setting()utility function - AttributeError is no longer raised; underlying MinIO SDK exceptions are raised instead (see docstrings for details)
- The project has migrated from
setup.pyto pyproject.toml - uv is now the default package and project manager
- Unit tests have been updated to run against a local MinIO container instead of play.min.io
IMPORTANT: Read the updated README.md thoroughly before beginning migration to understand the new architecture.
pip install --upgrade django-minio-backendChange your installed apps configuration to use the full app config path:
Before:
INSTALLED_APPS = [
# ...
'django_minio_backend',
]After:
INSTALLED_APPS = [
# ...
'django_minio_backend.apps.DjangoMinioBackendConfig',
]Delete these deprecated settings from your settings.py:
DEFAULT_FILE_STORAGESTATICFILES_STORAGE
Before (v3.x):
DEFAULT_FILE_STORAGE = 'django_minio_backend.models.MinioBackend'
MINIO_ENDPOINT = 'minio.your-company.co.uk'
MINIO_ACCESS_KEY = 'yourMinioAccessKey'
MINIO_SECRET_KEY = 'yourVeryS3cr3tP4ssw0rd'
MINIO_USE_HTTPS = True
MINIO_URL_EXPIRY_HOURS = timedelta(days=1)
MINIO_CONSISTENCY_CHECK_ON_START = True
MINIO_PRIVATE_BUCKETS = ['django-backend-dev-private']
MINIO_PUBLIC_BUCKETS = ['django-backend-dev-public']
MINIO_MEDIA_FILES_BUCKET = 'my-media-files-bucket' # <-- NOTE: This parameter name changes!
MINIO_BUCKET_CHECK_ON_SAVE = TrueAfter (v4.0.0+):
from datetime import timedelta
STORAGES = {
"default": {
"BACKEND": "django_minio_backend.models.MinioBackend",
"OPTIONS": {
"MINIO_ENDPOINT": "minio.your-company.co.uk",
"MINIO_ACCESS_KEY": "yourMinioAccessKey",
"MINIO_SECRET_KEY": "yourVeryS3cr3tP4ssw0rd",
"MINIO_USE_HTTPS": True,
"MINIO_URL_EXPIRY_HOURS": timedelta(days=1),
"MINIO_CONSISTENCY_CHECK_ON_START": True,
"MINIO_PRIVATE_BUCKETS": ['django-backend-dev-private', 'my-media-files-bucket'],
"MINIO_PUBLIC_BUCKETS": ['django-backend-dev-public'],
"MINIO_DEFAULT_BUCKET": "my-media-files-bucket", # <-- RENAMED from MINIO_MEDIA_FILES_BUCKET
"MINIO_BUCKET_CHECK_ON_SAVE": True,
},
},
}Important notes:
- All MinIO parameters are now nested within
OPTIONS MINIO_MEDIA_FILES_BUCKEThas been renamed toMINIO_DEFAULT_BUCKET- Add your default bucket to either
MINIO_PRIVATE_BUCKETSorMINIO_PUBLIC_BUCKETS
Model fields must now use lazy-loaded storage callables to avoid Django migration serialisation issues.
Before (v3.x):
from django.db import models
from django_minio_backend import MinioBackend, iso_date_prefix
class PrivateAttachment(models.Model):
file = models.FileField(
verbose_name="Object Upload",
storage=MinioBackend(bucket_name='django-backend-dev-private'),
upload_to=iso_date_prefix
)After (v4.0.0+):
Create a storages.py file in your app:
# myapp/storages.py
from django_minio_backend.models import MinioBackend
def get_private_storage():
return MinioBackend(
bucket_name='django-backend-dev-private',
storage_name='default', # References STORAGES["default"]
)
def get_public_storage():
return MinioBackend(
bucket_name='django-backend-dev-public',
storage_name='default',
)Update your models:
# myapp/models.py
from django.db import models
from django_minio_backend import iso_date_prefix
from .storages import get_private_storage
class PrivateAttachment(models.Model):
file = models.FileField(
verbose_name="Object Upload",
storage=get_private_storage, # Callable, not an instance
upload_to=iso_date_prefix
)If you were serving static files from MinIO in v3.x, update your configuration:
Before (v3.x):
STATICFILES_STORAGE = 'django_minio_backend.models.MinioBackendStatic'
MINIO_STATIC_FILES_BUCKET = 'my-static-files-bucket'After (v4.0.0+):
STORAGES = {
"default": {
# ... your default storage configuration
},
"staticfiles": {
"BACKEND": "django_minio_backend.models.MinioBackendStatic",
"OPTIONS": {
"MINIO_ENDPOINT": "minio.your-company.co.uk",
"MINIO_ACCESS_KEY": "yourMinioAccessKey",
"MINIO_SECRET_KEY": "yourVeryS3cr3tP4ssw0rd",
"MINIO_USE_HTTPS": True,
"MINIO_STATIC_FILES_BUCKET": "my-static-files-bucket",
"MINIO_CONSISTENCY_CHECK_ON_START": True,
},
},
}Important: Static file buckets are forced to be public in v4.0.0+ due to Django requirements.
After updating your model storage declarations, generate and apply new migrations:
python manage.py makemigrations
python manage.py migrateRun the health check to ensure everything is properly configured:
python manage.py is_minio_availableSolution: Ensure you're using callable storage functions in model fields, not direct class instances.
Solution: Verify that your static files bucket is configured and that STATIC_URL is defined (even though its value is ignored).
Solution: Ensure all storage declarations use lazy-loaded callables as shown in Step 5.
Solution: Verify all MinIO parameters are nested within the OPTIONS dictionary in your STORAGES configuration.
If you encounter issues not covered in this guide:
- Review the updated README.md
- Check the DjangoExampleProject directory for reference implementations
- Open an issue on GitHub