Package: django-drf-filepond
django-drf-filepond: A filepond server implementation for Django + Django REST Frameworkdjango-drf-filepondis a Django app that provides afilepondserver-side implementation for Django/Django REST Framework projects. The app can be easily added to your Django projects to provide a server-side API for the filepond file upload library.django-drf-filepond supports remote storage of uploads viadjango-storages:new: Release v0.5.0 is now available including Python 3.10 support, memory
efficiency improvements when working with large files, bug fixes and updates to
the testing infrastructure along with improved test coverage.:warning: Release v0.5.0 deprecates Python 2.7 and Python 3.5 support. This
will be the last release to support Python 2.7 and Python 3.5. Both these
versions of Python have now been "end-of-life" since 2020.:warning:Release v0.4.0 includes a database updatein relation to the large upload support. If you don't wish to apply DB migrations within your application at this stage, please continue to use django-drf-filepondv0.3.1. :warning:See theRelease Notessection for further release
information.Further documentation and a tutorial are available athttps://django-drf-filepond.readthedocs.io.InstallationThe app can be installed from PyPi:pip install django-drf-filepondor add it to your list of dependencies in arequirements.txtfile.ConfigurationThere are three key configuration updates to make within your Django application to set up django-drf-filepond:1. Add the app to INSTALLED_APPS:Add 'django-drf-filepond' toINSTALLED_APPSin your Django settings file (e.g.settings.py):...INSTALLED_APPS=[...,'django_drf_filepond']...2. Set the temporary file upload location:Set the location where you want django-drf-filepond to store temporary file uploads by adding theDJANGO_DRF_FILEPOND_UPLOAD_TMPconfiguration variable to your settings file, e.g.:importos...DJANGO_DRF_FILEPOND_UPLOAD_TMP=os.path.join(BASE_DIR,'filepond-temp-uploads')...3. Include the app urls into your main url configurationAdd the URL mappings for django-drf-filepond to your URL configuration inurls.py:fromdjango.urlsimportre_path,includeurlpatterns=[...re_path(r'^fp/',include('django_drf_filepond.urls')),]On the client side, you need to set the endpoints of theprocess,revert,fetch,load,restoreandpatchfunctions to match the endpoint used in your path statement above. For example if the first parameter tore_pathisfp/then the endpoint for the process function will be/fp/process/.(Optional) 4. File storage configurationInitially, uploaded files are stored in a temporary staging area (the location you set in item 2 above, with theDJANGO_DRF_FILEPOND_UPLOAD_TMPparameter. At this point, an uploaded file is still shown in the filepond UI on the client and the user can choose to cancel the upload resulting in the file being deleted from temporary storage and the upload being cancelled. When a user confirms a file upload, e.g. by submitting the form in which the filepond component is embedded, any temporary uploads need to be moved to a permanent storage location.There are three different options for file storage:Use a location on a local filesystem on the host server for file storage
(see Section 4.1)Use a remote file storage backend via thedjango-storageslibrary (see Section 4.2)Manage file storage yourself, independently ofdjango-drf-filepond(in this case, filepondloadfunctionality is not supported)More detailed information on handling file uploads and using thedjango-drf-filepondAPI to store them is provided in theWorking with file uploadssection below.4.1 Storage of filepond uploads using the local file systemTo use the local filesystem for storage, you need to specify where to store files. Set theDJANGO_DRF_FILEPOND_FILE_STORE_PATHparameter in your Django application settings file to specify the base location where stored uploads will be placed, e.g.:...DJANGO_DRF_FILEPOND_FILE_STORE_PATH=os.path.join(BASE_DIR,'stored_uploads')...The specified path for each stored upload will then be created relative to this location. For example, given the setting shown above, ifBASE_DIRwere/tmp/django-drf-filepond, then a temporary upload with the specified target location of either/mystoredupload/uploaded_file.txtormystoredupload/uploaded_file.txtwould be stored to/tmp/django-drf-filepond/stored_uploads/mystoredupload/uploaded_file.txtWhen using local file storage,DJANGO_DRF_FILEPOND_FILE_STORE_PATHis the only required setting.4.2 Remote storage of filepond uploads via django-storagesThedjango-storageslibrary provides support for a number of different remote file storage backends. Thedjango-storages documentationlists the supported backends.To enabledjango-storagessupport for django-drf-filepond, set theDJANGO_DRF_FILEPOND_STORAGES_BACKENDparameter in your application configuration to thedjango-storagesbackend that you wish to use. You need to specify the fully-qualified class name for the storage backend that you want to use. This is the same value that would be used for thedjango-storagesDEFAULT_FILE_STORAGEparameter and the required value can be found either by looking at thedjango-storages documentationfor the backend that you want to use, or by looking at thecode on GitHub.For example, if you want to use the SFTP storage backend, add the following to your application settings:...DJANGO_DRF_FILEPOND_STORAGES_BACKEND=\'storages.backends.sftpstorage.SFTPStorage'...or, for the Amazon S3 backend:...DJANGO_DRF_FILEPOND_STORAGES_BACKEND='storages.backends.s3boto3.S3Boto3Storage'...For each storage backend, there are a number of additionaldjango-storagesconfiguration options that must be specified. These are detailed in thedjango-storagesdocumentation.The following is an example of a complete set of configuration parameters for using an Amazon S3 storage backend for django-drf-filepond via django-storages:...DJANGO_DRF_FILEPOND_STORAGES_BACKEND='storages.backends.s3boto3.S3Boto3Storage'AWS_ACCESS_KEY_ID='<YOUR AWS ACCESS KEY>'AWS_SECRET_ACCESS_KEY='<YOUR AWS SECRET KEY>'AWS_STORAGE_BUCKET_NAME='django-drf-filepond'AWS_AUTO_CREATE_BUCKET=TrueAWS_S3_REGION_NAME='eu-west-1'...NOTE: django-storages is now included as a core dependency of django-drf-filepond. However, the different django-storages backends each have their own additional dependencieswhich you need to install manuallyor add to your own app's dependencies.You can add additional dependencies usingpipby specifying the optional extras feature tag, e.g. to install additional dependencies required for django-storages' Amazon S3 support run:$pipinstalldjango-storages[boto3]See theWorking with file uploadssection for more details on how to use the django-drf-filepond API to store files to a local or remote file store.NOTE:DJANGO_DRF_FILEPOND_FILE_STORE_PATHis not used when using a remote file store backend. It is recommended to remove this setting or leave it set to None.The base storage location for a remote file storage backend from django-storages is set using a setting specific to the backend that you are using - see the django-storages documentation for your chosen backend for further information.(Optional) 4. Set the permanent file store locationIf you wish to let django-drf-filepond manage the permanent storage of file uploads(note that this is required if you wish to use theloadmethod), you need to setDJANGO_DRF_FILEPOND_FILE_STORE_PATHin your application settings file, e.g....DJANGO_DRF_FILEPOND_FILE_STORE_PATH=os.path.join(BASE_DIR,'stored_uploads')...See"Working with file uploads"below for more information on how to move temporary uploads todjango-drf-filepond-managed permanent storage.Working with file uploadsWhen a file is uploaded from a filepond client, the file is placed into a uniquely named directory within the temporary upload directory specified by theDJANGO_DRF_FILEPOND_UPLOAD_TMPparameter. As per the filepondserver spec, the server returns a unique identifier for the file upload. In this case, the identifier is a 22-character unique ID generated using theshortuuidlibrary. This ID is the name used for the directory created underDJANGO_DRF_FILEPOND_UPLOAD_TMPinto which the file is placed. At present, the file also has a separate unique identifier which hides the original name of the file on the server filesystem. The original filename is stored within the django-drf-filepond app's database.When/if the client subsequently submits the form associated with the filepond instance that triggered the upload, the unique directory ID will be passed and this can be used to look up the temporary file.Chunked uploadsdjango-drf-filepondnow supports filepondchunked uploads. There is no configuration required fordjango-drf-filepondon the server side to handle chunked uploads.On the client side, you need to ensure that yourfilepond configurationspecifies server endpoints for both theprocessandpatchmethods and that you have the required configuration options in place to enable chunked uploads. For example, if you want to enablechunkUploadsand send uploads in 500,000 byte chunks, your filepond configuration should include properties similar to the following:FilePond.setOptions({...chunkUploads:true,chunkSize:500000,server:{url:'https://.../fp',process:'/process/',patch:'/patch/',revert:'/revert/',fetch:'/fetch/?target='}...});Storing file uploadsThere are two different approaches for handling temporary uploads that need to be stored permanently on a server after being uploaded from a filepond client via django-drf-filepond.These two approaches are not mutually exclusive and you can choose to use one approach for some files and the other approach for other files if you wish.1. Manual handling of file storageUsing this approach, you move the file initially stored as a temporary upload bydjango-drf-filepondto a storage location of your choice and the file then becomes independent ofdjango-drf-filepond. The following example shows how to lookup a temporary upload given its unique upload ID and move it to a permanent storage location. The temporary upload record is then deleted anddjango-drf-filepondno longer has any awareness of the file:importosfromdjango_drf_filepond.modelsimportTemporaryUpload# Get the temporary upload recordtu=TemporaryUpload.objects.get(upload_id='<22-char unique ID>')# Move the file somewhere for permanent storage# The file will be saved with its original nameos.rename(tu.get_file_path(),'/path/to/permanent/location/%s'%tu.upload_name)# Delete the temporary upload record and the temporary directorytu.delete()2. Use django-drf-filepond's API to store a temporary upload to permanent storageNote:You must use this approach for storing any files that you subsequently want to access using filepond'sloadfunction.Using this approach, the file is stored either to local storage or to a remote storage service depending on the file store configuration you are using.2.1store_uploadstore_uploadstores a temporary upload, uploaded as a result of adding it to the filepond component in a web page, to permanent storage.If you have configureddjango-drf-filepondto use local file storage by setting theDJANGO_DRF_FILEPOND_FILE_STORE_PATHparameter in your application settings, the file will be stored to a location under this directory.If you have configured a remote file store viadjango-storages, the stored upload will be sent to the configured storage backend viadjango-storages.Parameters:upload_id: The unique ID assigned to the upload bydjango-drf-filepondwhen the file was initially uploaded via filepond.destination_file_path: The location where the file should be stored. This location will be appended to the base file storage location as defined using theDJANGO_DRF_FILEPOND_FILE_STORE_PATHparameter, or, for remote storage backends, the location configured using the relevantdjango-storagesparameters. If you pass an absolute path beginning with/, the leading/will be removed. The path that you provide should also include the target filename.Returns:Adjango_drf_filepond.models.StoredUploadobject representing the stored upload.Raisesdjango.core.exceptions.ImproperlyConfiguredif using a local file store andDJANGO_DRF_FILEPOND_FILE_STORE_PATHhas not been set.RaisesValueErrorif:anupload_idis provided in an invalid formatthedestination_file_pathis not providedadjango_drf_filepond.models.TemporaryUploadrecord for the providedupload_idis not foundExample:fromdjango_drf_filepond.apiimportstore_upload# Given a variable upload_id containing a 22-character unique file upload ID:su=store_upload(upload_id,destination_file_path='target_dir/filename.ext')# destination_file_path is a relative path (including target filename.# The path will created under the file store directory and the original# temporary upload will be deleted.2.2get_stored_upload/get_stored_upload_file_dataGet access to a stored upload and the associated file data.get_stored_upload: Given anupload_id, return the associateddjango_drf_filepond.models.StoredUploadobject.Throwsdjango_drf_filepond.models.StoredUpload.DoesNotExistif a database record doesn't exist for the specifiedupload_id.get_stored_upload_file_data: Given a StoredUpload object, return the file data for the upload as a Pythonfile-like object.Parameters:stored_upload: Adjango_drf_filepond.models.StoredUploadobject for which you want retrieve the file data.Returns:Returns a tuple(filename, bytes_io)wherefilenameis a string representing the name of the stored file being returned andbytes_iois anio.BytesIOobject from which the file data can be read. If an error occurs, raises an exception:django_drf_filepond.exceptions.ConfigurationError: Thrown if using a local file store andDJANGO_DRF_FILEPOND_FILE_STORE_PATHis not set or the specified location does not exist, or is not a directory.FileNotFoundError: Thrown if using a remote file store and the file store API reports that the file doesn't exist. If using a local file store, thrown if the file does not exist or the location is a directory and not a file.IOError: Thrown if using a local file store and reading the file fails.Example:fromdjango_drf_filepond.apiimportget_stored_uploadfromdjango_drf_filepond.apiimportget_stored_upload_file_data# Given a variable upload_id containing a 22-character unique# upload ID representing a stored upload:su=get_stored_upload(upload_id)(filename,bytes_io)=get_stored_upload_file_data(su)file_data=bytes_io.read()2.3delete_stored_uploaddelete_stored_uploaddeletes a stored upload record and, optionally, the associated file that is stored on either a local disk or a remote file storage service.Parameters:upload_id: The unique ID assigned to the upload bydjango-drf-filepondwhen the file was initially uploaded via filepond.delete_file:Trueto delete the file associated with the record,Falseto leave the file in place.Returns:ReturnsTrueif the stored upload is deleted successfully, otherwise raises an exception:django_drf_filepond.models.StoredUpload.DoesNotExistexception if no upload exists for the specifiedupload_id.django_drf_filepond.exceptions.ConfigurationError: Thrown if using a local file store andDJANGO_DRF_FILEPOND_FILE_STORE_PATHis not set or the specified location does not exist, or is not a directory.FileNotFoundError: Thrown if using a remote file store and the file store API reports that the file doesn't exist. If using a local file store, thrown if the file does not exist or the location is a directory and not a file.OSError: Thrown if using a local file store and the file deletion fails.fromdjango_drf_filepond.apiimportdelete_stored_upload# Given a variable upload_id containing a 22-character unique# upload ID representing a stored upload:delete_stored_upload(upload_id,delete_file=True)# delete_file=True will delete the file from the local# disk or the remote storage service.DRF PermissionsBy default no permissions are applied on API endpoints. If you want to assign certain permissions such asrest_framework.permissions.IsAuthenticatedyou can do it like so:DJANGO_DRF_FILEPOND_PERMISSION_CLASSES={'GET_FETCH':['rest_framework.permissions.IsAuthenticated',],'GET_LOAD':['rest_framework.permissions.IsAuthenticated',],'POST_PROCESS':['rest_framework.permissions.IsAuthenticated',],'GET_RESTORE':['rest_framework.permissions.IsAuthenticated',],'DELETE_REVERT':['rest_framework.permissions.IsAuthenticated',],'PATCH_PATCH':['rest_framework.permissions.IsAuthenticated',],}You can add more than one permission for each endpoint.The above list includes all the permission names currently defined on django-drf-filepond views. The naming convention used is<METHOD_NAME>_<ENDPOINT_NAME>where<METHOD_NAME>is the method name used for a request and<ENDPOINT_NAME>is the URL endpoint called. So, for example, aPOSTrequest to/fp/processwould be handled by the permission classes defined forPOST_PROCESS.Release notesv0.5.0django-drf-filepond v0.5.0 includes additional functionality and bug fixes:Add Python 3.10 supportMemory efficiency improvements when handling large files. Previously, the
way chunked uploads were handled meant that twice as much memory as the size
of an upload was being used. This has been resolved with an extensive
redesign of the chunked upload handler.Testing of the code has been switched to use Pytest with Tox.Test coverage has been significantly improved.:warning:Please note:v0.5.0 deprecates Python 2.7 and Python 3.5 support.
This will be the last release to support Python 2.7 and Python 3.5. Both these
versions of Python have now been "end-of-life" since 2020. :warning:See full details of the particular changes merged in thev0.5.0 release notes on GitHub.v0.4.0Adds support for large file uploads (> ~2GB) (see#57).:warning:Release v0.4.0 includes a database updatein relation to the large upload support. If you don't wish to apply DB migrations within your application at this stage, please continue to use django-drf-filepondv0.3.1. :warning:v0.3.0Adds support for filepond chunked uploads.LicenseThis repository is licensed under a BSD 3-Clause license. Please see theLICENSEfile in the root of the repository.AcknowledgementsThanks topqinafor producing thefilepondfile upload library that this Django app provides server-side support for.The django-drf-filepond app has been built as part of work that is being supported by UK Research and Innovation (Engineering and Physical Sciences Research Council) under grant EP/R025460/1.