Package: django-s3-file-field
django-s3-file-fielddjango-s3-file-field is a Django library for uploading files directly toAWS S3orMinIOStorage from HTTP clients
(browsers, CLIs, etc.).Benefitsdjango-s3-file-field makes long-running file transfers (with large files or slow connections)
more efficient, as the file content is no longer proxied through the Django server. This also frees
Django from needing to maintain active HTTP requests during file upload, decreasing server load and
facilitating deployment to environments likeHeroku, which have short, strict request timeouts.ScopeThe principal API of django-s3-file-field is theS3FileField, which is a subclass ofDjango'sFileField.
django-s3-file-field does not affect any operations other than uploading from external HTTP
clients; for all other file operations (downloading, uploading from the Python API, etc.), refer toDjango's file management documentation.django-s3-file-field supports both the creation and modification (by overwrite) ofS3FileField-containingModelinstances.
It supports server-rendered views, via the Forms API, with FormFieldandWidgetsubclasses
which will automatically be used forModelForminstances.
It also supports RESTful APIs, via Django Rest Framework's Serializer API, with a
SerializerFieldsubclass which will automatically be used forModelSerializerinstances.Installationdjango-s3-file-field must be used with a compatible Django Storage, which are:S3Storageindjango-storages,
forAWS S3MinioStorageorMinioMediaStorageindjango-minio-storage,
forMinIOAfter the appropriate Storage is installed and configured, install django-s3-file-field, using the
corresponding extra:pipinstalldjango-s3-file-field[s3]orpipinstalldjango-s3-file-field[minio]Enable django-s3-file-field as an installed Django app:# settings.pyINSTALLED_APPS=[...,'s3_file_field',]Add django-s3-file-field's URLconf to the root URLconf; the path prefix ('api/s3-upload/')
can be changed arbitrarily as desired:# urls.pyfromdjango.urlsimportinclude,pathurlpatterns=[...,path('api/s3-upload/',include('s3_file_field.urls')),]UsageFor all usage, define anS3FileFieldon a DjangoModel, instead of aFileField:fromdjango.dbimportmodelsfroms3_file_fieldimportS3FileFieldclassResource(models.Model):blob=S3FileField()Django FormsWhen defining aDjangoModelForm,
the appropriate FormFieldwill be automatically used:fromdjango.formsimportModelFormfrom.modelsimportResourceclassResourceForm(ModelForm):classMeta:model=Resourcefields=['blob']Forms using django-s3-file-field include additionalassets, which it's essential to render
along with the Form. Typically, this can be done in any Form-containing Template as:<head>
  {# Assuming the Form is availible in context as "form" #}
  {{ form.media }}
</head>Django Rest FrameworkWhen defining aDjango Rest FrameworkModelSerializer,
the appropriate SerializerFieldwill be automatically used:fromrest_frameworkimportserializersfrom.modelsimportResourceclassResourceSerializer(serializers.ModelSerializer):classMeta:model=Resourcefields=['blob']Clients interacting with these RESTful APIs will need to use a corresponding django-s3-file-field
client library. Client libraries (and associated documentation) are available for:PythonJavascript / TypeScriptPytestWhen installed, django-s3-file-field makes severalPytest fixturesautomatically
available for use.Thes3ff_field_valuefixture will return a valid input value for DjangoModelFormor
Django Rest FrameworkModelSerializersubclasses:from.formsimportResourceFormdeftest_resource_form(s3ff_field_value:str)->None:form=ResourceForm(data={'blob':s3ff_field_value})assertform.is_valid()Alternatively, thes3ff_field_value_factoryfixture transforms aFileobject into a valid input
value (for DjangoModelFormor Django Rest FrameworkModelSerializersubclasses), providing
more control over the uploaded file:fromdjango.core.files.storageimportdefault_storagefromrest_framework.testimportAPIClientdeftest_resource_create(s3ff_field_value_factory):client=APIClient()stored_file=default_storage.open('some_existing_file.txt')s3ff_field_value=s3ff_field_value_factory(stored_file)resp=client.post('/resource',data={'blob':s3ff_field_value})assertresp.status_code==201