Package: dj-kaos-storages
DJ KAOS StoragesA set of django media storage classes for different use cases such as private file storage on S3. An extension
ofjschneier'sdjango-storagesQuick Startpipinstalldj-kaos-storages# settings.pyimportosAWS_ACCESS_KEY_ID=os.environ['DJANGO_AWS_ACCESS_KEY_ID']AWS_SECRET_ACCESS_KEY=os.environ['DJANGO_AWS_SECRET_ACCESS_KEY']AWS_STORAGE_BUCKET_NAME=os.environ['DJANGO_AWS_STORAGE_BUCKET_NAME']AWS_S3_REGION_NAME=os.environ.get('DJANGO_AWS_S3_REGION_NAME',None)STORAGES_PUBLIC_MEDIA_LOCATION='media'STORAGES_PRIVATE_MEDIA_LOCATION='private-media'PUBLIC_FILE_STORAGE='kaos_storages.s3.PublicMediaFilesS3Storage'PRIVATE_FILE_STORAGE='kaos_storages.s3.PrivateMediaFilesS3Storage'# default storage is set to private, switch to PUBLIC_FILE_STORAGE for public default storageDEFAULT_FILE_STORAGE=PRIVATE_FILE_STORAGEifDEFAULT_FILE_STORAGE==PRIVATE_FILE_STORAGE:MEDIA_URL=f'https://{AWS_STORAGE_BUCKET_NAME}.s3.amazonaws.com/{STORAGES_PRIVATE_MEDIA_LOCATION}/'ifDEFAULT_FILE_STORAGE==PUBLIC_FILE_STORAGE:MEDIA_URL=f'https://{AWS_STORAGE_BUCKET_NAME}.s3.amazonaws.com/{STORAGES_PUBLIC_MEDIA_LOCATION}/'Now if somebody goes to the urlhttps://your-bucket.s3.amazonaws.com/private-media/path/to/your/file, they would get a
403, effectively making your media files private. The project loads the private media assets by appending a signature
url param, that is only valid for a short period of time.RationaleIt is a good idea to not store user uploaded files (i.e. media files) on the server you are running your application in.
If you need to shut down the server, or it goes down for any reason, all those files are lost. Also storing user
uploaded files on a server would potentially take up a massive amount of storage space on the server. For that reason it
is better to store such files on a storage service such as S3. This package is an extension ofdjango-storagesand allows a few more granular common use cases.Public vs Private media filesIf you want media files to be only accessible through your application, and want to prevent users to put in the url in
their browsers and access the files, you'd want to use a private media file storage. For example your application might
generate confidential PDF report files that you want to only be accessible through your dashboard and not using a
publicly available URL.AWS S3dj-kaos-storage comes with 3 classes to handle external storage on Amazon S3. All the following classes require adding
the necessary settings fordjango-storages. Refer todjango-storages'sdocumentationfor more details.AWS_ACCESS_KEY_ID=os.environ['DJANGO_AWS_ACCESS_KEY_ID']AWS_SECRET_ACCESS_KEY=os.environ['DJANGO_AWS_SECRET_ACCESS_KEY']AWS_STORAGE_BUCKET_NAME=os.environ['DJANGO_AWS_STORAGE_BUCKET_NAME']AWS_S3_REGION_NAME=os.environ.get('DJANGO_AWS_S3_REGION_NAME',None)StaticFilesS3StorageTo store static files on S3. The management commandcollectstaicwill put all your static files on S3 at the location
described bysettings.STORAGES_STATICFILES_LOCATION. In order to use this class:# settings.pySTORAGES_STATICFILES_LOCATION='static'# or anything else for that matterSTATICFILES_STORAGE='kaos_storages.s3.StaticFilesS3Storage'Note you can omitsettings.STORAGES_STATICFILES_LOCATION, and by default it is set tostatic.PublicMediaFilesS3StorageTo store public media files on S3. In order to use:# settings.pySTORAGES_PUBLIC_MEDIA_LOCATION='media'# or anything else for that matterPUBLIC_FILE_STORAGE='kaos_storages.s3.PublicMediaFilesS3Storage'DEFAULT_FILE_STORAGE=PUBLIC_FILE_STORAGEMEDIA_URL=f'https://{AWS_STORAGE_BUCKET_NAME}.s3.amazonaws.com/{STORAGES_PUBLIC_MEDIA_LOCATION}/'PrivateMediaFilesS3StorageTo store private media files on S3. In order to use:# settings.pySTORAGES_PRIVATE_MEDIA_LOCATION='private-media'# or anything else for that matterPRIVATE_FILE_STORAGE='kaos_storages.s3.PrivateMediaFilesS3Storage'DEFAULT_FILE_STORAGE=PRIVATE_FILE_STORAGEMEDIA_URL=f'https://{AWS_STORAGE_BUCKET_NAME}.s3.amazonaws.com/{STORAGES_PRIVATE_MEDIA_LOCATION}/'How to use both private and public media storage in a projectIt is possible to use both public and private media storage in a project. In order to do so, first decide which mode of
storage is going to be the default one. We suggest if you are developing an internal facing application (such as a
company dashboard) to use private media storage as the default. If you are developing a public facing application
(i.e. a social network) to use public media storage as the default. In the case you need to store some file privately
when the default is public (and vice versa) use the following method:# settings.pySTORAGES_PUBLIC_MEDIA_LOCATION='media'STORAGES_PRIVATE_MEDIA_LOCATION='private-media'PUBLIC_FILE_STORAGE='kaos_storages.s3.PublicMediaFilesS3Storage'PRIVATE_FILE_STORAGE='kaos_storages.s3.PrivateMediaFilesS3Storage'# default being publicDEFAULT_FILE_STORAGE=PUBLIC_FILE_STORAGEMEDIA_URL=f'https://{AWS_STORAGE_BUCKET_NAME}.s3.amazonaws.com/{STORAGES_PUBLIC_MEDIA_LOCATION}/'# default being privateDEFAULT_FILE_STORAGE=PRIVATE_FILE_STORAGEMEDIA_URL=f'https://{AWS_STORAGE_BUCKET_NAME}.s3.amazonaws.com/{STORAGES_PRIVATE_MEDIA_LOCATION}/'In your django models, say the default is private storage, and you want some model's field's uploaded files to be
public:fromdjango.dbimportmodelsfromkaos_storages.s3importPublicMediaFilesS3Storage# models.pyclassSomeModelWithPublicFileField(models.Model):file=models.FileField(storage=PublicMediaFilesS3Storage)Keep in mind, you might have different settings for your local and production environments. Most likely your local
environment doesn't differentiate between public and private file uploads, and has no concept of S3 andPublicMediaFilesS3Storage.PublicFileFieldandPrivateFileFieldFor your conveniencedj-kaos-storagescomes with a number ofFileFieldclasses and mixins that abstracts the above
that set the storage class of the field to class importable from the path described bysettings.PUBLIC_FILE_STORAGEandsettings.PRIVATE_FILE_STORAGEfor public and private uploads, respectively. WhenDEBUG=Truewhich signals a dev
environment,PUBLIC_FILE_STORAGEandPRIVATE_FILE_STORAGEare set by default todjango.core.files.storage.FileSystemStorage, which is the Django default. This way the helper classes such
asPublicFileFieldandPrivateFileFieldwill save to your filesystem in your local development environment. If your
settings has setPUBLIC_FILE_STORAGEand/orPRIVATE_FILE_STORAGEthey are respected and won't be overridden (e.g.
you turn onDEBUG = Truein a staging environment).In the example above:fromdjango.dbimportmodelsfromkaos_storages.fieldsimportPublicFileField# models.pyclassSomeModelWithPublicFileField(models.Model):file=PublicFileField()Notice how we swapped the defaultmodels.FileFieldwithkaos_storages.fields.PublicFileField.List of all fields available:PublicFileFieldPrivateFileFieldPublicImageFieldPrivateImageFieldThere are also two mixins classes available, so you can create your own children ofFileField:PublicFileFieldMixinPrivateFileFieldMixinDevelopment and TestingIDE SetupAdd theexampledirectory to thePYTHONPATHin your IDE to avoid seeing import warnings in thetestsmodules. If
you are using PyCharm, this is already set up.Running the TestsInstall requirementspip install -r requirements.txtFor local environmentpytestFor all supported environmentstox