Local filesystem as a remote storage in Django

Question:

I use Amazon S3 as a part of my webservice. The workflow is the following:

  • User uploads lots of files to web server. Web server first stores them locally and then uploads to S3 asynchronously
  • User sends http-request to initiate job (which is some processing of these uploaded files)
  • Web service asks worker to do the job
  • Worker does the job and uploads result to S3
  • User requests the download link from web-server, somedbrecord.result_file.url is returned
  • User downloads result using this link

To work with files I use QueuedStorage backend. I initiate my FileFields like this:

Where queued_s3storage is an object of class derived from ...backends.QueuedStorage and remote field is set to '...backends.s3boto.S3BotoStorage'.

Now I’m planning to deploy the whole system on one machine to run everything locally, I want to replace this '...backends.s3boto.S3BotoStorage' with something based on my local filesystem.

The first workaround was to use FakeS3 which can “emulate” S3 locally. Works, but this is not ideal, just extra unnecessary overhead.

I have Nginx server running and serving static files from particular directories. How do I create my “remote storage” class that actually stores files locally, but provides download links which lead to files served by Nginx? (something like http://myip:80/filedir/file1). Is there a standard library class for that in django?

Answer:

The default storage backend for media files is local storage.

Your settings.py defines these two environment variables:

  • MEDIA_ROOT (link to docs) — this is the absolute path to the local file storage folder
  • MEDIA_URL (link to docs) — this is the webserver HTTP path (e.g. '/media/' or '//%s/media' % HOSTNAME

These are used by the default storage backend to save media files. From Django’s default/global settings.py:

This configured default storage is used in FileFields for which no storage kwarg is provided. It can also be accessed like so: rom django.core.files.storage import default_storage.


So if you want to vary the storage for local development and production use, you can do something like this:

And in your models:


Lastly, you want nginx to serve the files directly from your MEDIA_URL. Just make sure that the nginx URL matches the path in MEDIA_URL.

Leave a Reply