Saving file field uploads not in MEDIA_ROOT directory

I had a requirement recently to upload files to some kind of a private directory, not accessible via www. Of course, I used Django model's FileField to solve the task, but the problem was in a fact that by default, FileField saves uploads under MEDIA_ROOT which is not what I wanted. 

Luckily, Django has a pretty simple solution to the problem, all you need is to extend default file storage a little bit and pass it to our file field, like that:

1) At first lets define our private storage path, it's better to put it into your app configuration, like this:

1
2
3
4
5
  1. # settings.py
  2. ...
  3. PRIVATE_STORAGE_ROOT = join(BASE_DIR, 'private')
  4. ...

2) Now update your model:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
  1. # models.py
  2. from django.conf import settings
  3. from django.core.files.storage import FileSystemStorage
  4. from django.db import models
  5. private_storage = FileSystemStorage(location=settings.PRIVATE_STORAGE_ROOT)
  6. class MyModel(models.Model):
  7. upload = models.FileField(storage=private_storage)

That's all. Make sure your 'private' directory exists and that should be it.