In this blog, the goal is to show the capabilities of Django’s built-in Fields, specifically Django FileField, for storing files. Every experienced web developer had to work with files at one point. Files can be stored in a database in many ways, either locally or on a server.
So what actually is FileField in Django?
Django FileField inherits an abstract Field class representing the database table column, and it is used for simple file uploads.
Before we go into a more detailed explanation of the FileField parameters, we will define one model with a
class Book(models.Model): title = models.CharField(max_length=255) published_date = models.DateTimeField(null=True) pdf_file = models.FileField()
Let’s look at how FileField behaves in the database and what we use it for.
Django FileField in Database
For the specified model after
python manage.py makemigrations the following migration file is obtained.
class Migration(migrations.Migration): initial = True dependencies = [ ] operations = [ migrations.CreateModel( name='Book', fields=[ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('title', models.CharField(max_length=255)), ('published_date', models.DateTimeField(null=True)), ('pdf_file', models.FileField(upload_to='')), ], ), ]
And after migrating
python manage.py migrate we get the following data structure in the database:
|Name||Data Type||Database Example|
|title||Character Varying (255)||Django FileField Book|
|published_date||Timestamp with time zone||2022-01-19 16:56:03+01|
|pdf_file||Character Varying (100)||django_filefield_book.pdf|
We see one interesting thing, FileField is stored in the Postgres database as Character Varying.
What would that mean for our files? Where do they end up?
Our files are stored locally on the computer. So in this example, the FileField or
pdf_file column in the database would save the path of our file.
Let’s look at the FileField parameters.
Django FileField parameters
class FileField(upload_to=None, max_length=100, **options)
FileField has 2 optional parameters. Let’s see in the following example what these parameters actually mean.
pdf_file = models.FileField(upload_to='uploads/', max_length=255, **options)
upload_tospecifies the route to which a particular file will be saved. For example, book.pdf will be saved in the
BASE_DIR/uploadsdirectory, the file name and folder in which the file is located will be saved in the database.
max_lengthdetermines the maximum length of the saved path. The default is 100. If you have files and paths with long names, you must not forget to change this parameter. Otherwise, you might get
DatabaseError: value too long for type character varying (100).
Finally, let’s look at an example of a saved book in the database:
Although we have defined the directory in which we save the files, it is still not the best practice.
According to the official Django documentation, the files should be saved in the MEDIA folder. The media folder should be defined in the Django settings, so let’s show what it should look like.
Define next in your settings.py.
MEDIA_ROOT = os.path.join(BASE_DIR, 'media') MEDIA_URL = '/media/'
From the moment we define MEDIA_ROOT, all subsequent files we upload will be saved in
media/uploads/ because we defined
upload_to = 'uploads'. But only the file path
upload_to + file_name is saved in the database.
Now that we have successfully saved our files to the computer. How can we retrieve these files?
How to access FileField files?
We access our files via URL with the exposed path to the file.
So let’s try to access our file saved in
We simply send a GET request to
http://127.0.0.1:8000/media/uploads/book.pdf, but we get:
Not Found: /media/uploads/book.pdf
"GET /media/uploads/book.pdf HTTP/1.1" 404
So why is that so?
This happens because the path is not defined in urls.py, i.e., Django tries to find a valid path to the file we are looking for, but as it does not find the right URL, it concludes that it does not exist.
So the next step is to define a valid URL, but since files can be named differently, how do we do that?
It is quite simple, we previously defined the MEDIA folder, and it now stores files. We just have to expose that file in URLs, so we can then access everything in it in the following way:
host + media_root + upload_to parameter (what is saved in the database as varchar)
Let’s see how to expose a URL. Set the following in root URLs:
from django.conf import settings from django.conf.urls.static import static urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
WARNING - use this only in Development! This method of serving static files is NOT safe in production. Read more in the official Django documentation
Now that we’ve exposed the files, we can finally retrieve the file via URL. Assuming you’re running this locally, let’s type the following:
http://127.0.0.1:8000/ + media/ + upload_to parameter
In this example, considering
upload_to parameter is uploads/book.pdf:
The uploaded pdf is displayed in the web browser, and we get:
"GET /media/uploads/book.pdf HTTP / 1.1" 200
NOTE - Occasionally we can get a response with status code 304. No need to worry, it's a redirection to a cached resource.
FileField with Django ORM
Object-relational mapping helps us create queries over the database without writing actual SQL queries. So it can be pretty handy.
In the following example, we will show what can be done with Django ORM.
# Filters books using string manipulation of pdf_file Book.objects.filter(pdf_file__exact='uploads/book.pdf') Book.objects.filter(pdf_file__iexact='uploads/BOOK.pdf') Book.objects.filter(pdf_file__contains='book') Book.objects.filter(pdf_file__endswith=".pdf") Book.objects.filter(pdf_file__startswith="uploads") # Filters books using regex Book.objects.filter(pdf_file__regex='book') # Filters books by existing pdf_file Book.objects.filter(pdf_file__isnull=False) # Filters books by given array of pdf_files Book.objects.filter(pdf_file__in=['uploads/book.pdf'])
As we can see, since pdf_column is character varying in the database, we can do all the standard operations on it, which we could do with CharField, for example. Here are just a few, mostly retrieving books using string operations.
FileField is a powerful tool for saving files. However, it is also dangerous to misuse and expose files that we should not reveal. Now you can use everything you learned and finally start uploading files to your application.
I hope you found this blog post helpful!