In this tutorial, we are going to explain how to create a Django project which allows a user to upload a file to the server and how Django handles the whole process of file uploading.
When Django is used to upload a user's file to the server, it places the uploaded file in request.FILES. The request.FILES is a multivalue dictionary object with its key being the name of the file uploaded and its value being the instance of UploadedFile.
Each file stored in request.FILES is an instance of UploadedFile.
So let us create a Django project to explain you how to work manage the file upload using Django Framework. For those who have not read our last tutorials and for those who don't know how to create a Django project, here is a recap.
Creating a Django project
To create a directory for our project, we need to open the Command Prompt and type in the command -
django-admin startproject django_file_handling
dhago-admin is a management utility for Django Framework, using which we could create a new project and much more.
startproject is a command to start a new Django project.
django_file_handling is the name of our Django project and also the name of our project directory created in the current directory.
The startproject command gives us a sub-directory and files
Executing the startproject command has not only created a project directory named django_file_handling, but has also created a file manage.py and another sub-directory
with the same name as the project directory, which also contains some Python files -
django_file_handling is the root directory of our Django project, also known as the container of our project.
manage.py is a command-line utility which allows us to interact with Django project in various ways.
django_file_handling sub-directory is actually a Python package for our project. We can import this package(a group of modules) and its contents just like we import any general Python package/module and its contents.
__init__.py is a file which allows our sub-directory django_file_handling to be treated as a Python package.
settings.py is a file used for setting the configurations for our Django project.
urls.py is a file used to specify the URL declarations for our Django project, also known as a a table of contents.
wsgi.py is a file used as an entry-point for WSGI web-servers to serve your project.
Starting the development server
After creating the project directory and the files required to run our Django project, it is time to execute the Django Development Server. To do this,
we will have to open the command prompt, change the current directory to the root directory of our Django project and execute the following command.
python manage.py runserver
Executing the above mentioned command will trigger the Django Development Server in action, as you can see in the picture below.
E:\Django Projects\django_file_handling>python manage.py runserver
Watching for file changes with StatReloader
Performing system checks...
System check identified no issues (0 silenced).
You have 16 unapplied migration(s). Your project may not work properly until you
apply the migrations for app(s): admin, auth, contenttypes.
Run 'python manage.py migrate' to apply them.
September 23, 2019 - 17:37:35
Django version 2.2.1, using settings 'django_file_handling.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CTRL-BREAK.
Now that you have successfully started the Django development server, it is time to visit the http://127.0.0.1:8000/ link and you will see a webpage displaying a congratulatory message, as shown below.
Note: The runserver command runs the Django development server at the port 8000.
Creating an app in our project
A project may contain one or multiple applications. As we have already created a project, now let us create a welcome application in it which welcomes the user. This application will be created right under our root - project directory django_file_handling.
To create an application, we have to open another window command prompt, change the current directory to the root directory of our Django project and execute the following command -
python manage.py startapp file_upload
The command startapp in combination with manage.py utility is used to create an app of a project, using which we have created an app named - file_upload.
Executing the startapp command has not only created an application directory named file_upload in the root - project directory, but has also created the following set of Python files -
In order to allow a user to upload a file, we will have to provide an HTML form to the user. As you must know that an HTML form is
a collection of form elements such as a textbox, checkbox, submit buttons, file uploading button, etc. These form elements
allow us to take input from the user and send the collected input to the server.
For this purpose, we are going to create an HTML template file within our application folder file_upload, we will name this file template.htm.
Must Read:
As we have explained at the beginning of this article, the file uploaded by the user is stored in request.FILES. The request.FILES will only contain the file data if the two requirements are met:
The request method in the <form> was POST.
The <form> that posted the request has an attribute enctype= multipart/form-data"
Note: The request.FILES will be empty in the absence of any of the two must requirements.
Keeping the above mentioned important points, we will create an HTML template file in which we will define an HTML form with the necessary elements
template.htm
<html>
<head><title>Django Framework with file_upload - Decodejava.com</title></head>
<body>
Welcome! Please fill the form below:
<form method="POST" enctype="multipart/form-data">
{% csrf_token %}
{{ form|linebreaks }}
<button type="submit">Save</button>
</form>
</body>
</html>
This HTML template file contains two parts:
In this HTML template file, we have specified a variable - form within the double curly brackets {{ }}.
This form variable allow us to access the form fields specified in the forms.py(going to create it next) and dynamically insert them in this HTML template file.
The static part, such as a submit button which actually sends the form data.
Note:
We have used the form variable with the linebreaks filter, which installs an HTML linebreak <br/> in the HTML template file, after displaying each form field specified the forms.py.
Creating the Form class - forms.py
Up next, we are going to create a form class named NameForm by extending the in-built Form class. This file will be created within the application i.e. forms folder.
forms.py
from django import forms
class UserForm(forms.Form):
name = forms.CharField(label="Enter your name", max_length = 10)
age = forms.IntegerField(label='Enter your age ')
email = forms.EmailField(label="Enter your Email")
# Field for creating file input
file = forms.FileField()
As you can see in the form class UserForm, we have specified its four fields:
The field name name is based on the Field class CharField, for char input.
The field name age is based on the Field class IntegerField, for integer input.
The field name email is based on the Field class EmailField, for email input.
The field name file is based on the Field class FileField, for file input.
Creating the view - view.py
Once we have created the HTML template file in the application, we will also need to create a view which comprises of one of more view functions.
A view function is simply a Python function which takes an HttpRequest from the HTML template file and returns an HttpResponse with the values of the variables specified and requested by the HTML template file, such as - form variable specified within the HTML template file.
Note: This view functions are defined in the file view.py, which is already created and stored in our application directory, file_upload. Let us just copy and paste the following code in view.py.
view.py
from django.shortcuts import render
from django.http import HttpResponse
from .forms import UserForm
# This view function is used when the form is requested for the first time to display it to the user
def get_form(request):
form = UserForm()
return render(request, 'template_ex.htm', {'form': form})
# A simple function, called by the process_form view function to write the uploaded file to a specific directory.
def manage_file_upload(f):
with open('file_upload/uploaded files/' + f.name, 'wb+') as destination:
for chunk in f.chunks():
destination.write(chunk)
# This view function is called when submit button is pressed by the user after filling the form details.
def process_form(request):
# Handling the POST request to process the form data
if request.method == 'POST':
# Creating a form instance and populating it with data from the request
user = UserForm(request.POST, request.FILES)
# Check whether the form data is valid, if yes, HTTPResponse displays an appropriate page.
if user.is_valid():
manage_file_upload(request.FILES['file'])
return HttpResponse("Thank you for submitting your profile!")
In this view.py file, we have imported the render function from the django.shortcuts module and have defined two view functions:
get_form, used to display the form to the user for the first time.
process_form, used to process the form data sent by the user.
The view function - get_form takes an HttpRequest object in its parameter and we have named this parameter - request.
Note:Each view function takes an HttpRequest object in its first parameter and it could named anything but its typically named - request.
In this view function, we have simply created an object of UserForm Form class.
To initiate the process of rendering, we call the render() method, which replaces the form variable declared in HTML template file with the values of form fields specified in the UserForm class.
The render() method requires three parameters passed to it:
Request - An incoming request.
Path to the HTML template - This is a path relative to the path specified in settings.py file.
Context - Since, Django 1.8+ version, the render() method takes a Context, which should be represented by a dictionary of variables needed in the template.
On call, the render() method renders the request from template_ex.htm page and returns an HttpResponse object with the rendered form fields.
The process_form view function processes the form data submitted by the user, when the form is sent by using the HTTP POST method.
In the process_form view function, we have created a form instance by populating it with data from the request and an extra parameter request.FILES has been used in the constructor, as it contains instance of the uploaded file.
In the process_form view function, we have called the is_valid() method on the Form instance(referring to UserForm), which runs the validation checks on all the form fields specified in the UserForm class.
If the form data send by the user is valid then it will call the function manage_file_upload, which will write the th file to a directory specified within the manage_file_upload function.
Finally, the view function process_form calls the render() method to render a page which displays the message Thank you for submitting your profile!.
Mapping URL to view
After creating the view functions of an application, we need to specify the mapping between a URL and each view function in a file named - urls.py. The file urls.py is simply coded in Python and we will have to create the urls.py file in the folder of our application, file_upload.
The use of mapping a URL to the view function is, when this URL is requested by the user, its mapped view function is executed and a response is returned.
urls.py
from django.urls import path
from . import views
urlpatterns = [
path('', views.get_form),
path('form_submit/', views.process_form),
]
As you can see in the file urls.py, we have imported the path() function from the module django.urls.
The path() function has been passed the two must arguments -
An empty string to specify the URL pattern, specified by ' ', this empty string will be matched to the view function - get_form.
A string 'form_submit/' will be matched to the view function - process_form, defined in the application's views.py.
Note:
This URL pattern specified in the application's urls.py file gets added to another URL pattern, specified in the project's urls.py file(we are going to create it next), and the combined path will be matched to the view functions defined in the application's views.py.
Pointing the project URL to application URL
Next, we are going to point the project URL(urls.py) to the application URL(urls.py) by using the include() function. For this, we will open the file urls.py in the root - project directory, django_file_handling, and copy-paste the following code.
urls.py
from django.contrib import admin
from django.urls import include, path
urlpatterns = [
path('welcome/template/', include('file_upload.urls')),
]
As you can see in the file urls.py, we have imported the path() and include() function from the module django.urls.
The path() function has been passed the two must arguments -
A string to specify the URL pattern - 'welcome/template/'. This is the relative path to the template.
This URL pattern, combined with the URL pattern defined in the application's urls.py will be matched to the view function - templ, which is specified in the application urls.py file(stored in the application directory file_upload). Therefore we have used the include() function to include and refer to the application's urls.py file.
How to load the HTML template file.
Next, we are going to show how to load the above created HTML template file template.htm, which is stored within our application folder file_upload.
To load the HTML template file, we need to specify its full path in the configuration file - settings.py, which is stored in the project folder. For our example, you can find this file in the sub-directory django_file_handling within our project django_file_handling i.e. - django_file_handling/django_file_handling/settings.py.
Within the settings.py file, you need to locate the property DIRS and copy-paste the full-path to the HTML template file against it, as shown below and save the file.
And finally, it's time to execute our Django project with templates.
Executing the application of our project
To execute the file_upload application of our project django_file_handling, we just have to enter the address - http://127.0.0.1:8000/welcome/template/. This displays the form as shown below.
As you can see in the picture, the string welcome/template in the URL is the URL-pattern which gets matched to the URL pattern specified in the project urls.py file, which calls the application's urls.py and its associated view function - get_form(in the application) is executed and its response i.e.form with its elements(fields) is displayed within the HTML template file template.htm.
Next, when a user has filled the form with data and have also selected a file to upload i.e. funny sound.mp3.
On clicking the submit button, the user is displayed a webpage with an appropriate notification as shown below and the user file is uploaded to the directory specified in the manage_file_upload() function in the views.py i.e. within the file_upload/uploaded files directory.
Phew! This concludes the tutorial of creating and using an HTML form using Django Framework. See you in the next one!