Upload a File in Django

  1. Set the Django Environment
  2. Setup Django Project
  3. Test the Server
  4. Update settings.py File
  5. Create a Model
  6. Create a Form to Upload Files
  7. Add Views
  8. Configure the urls.py File
  9. Testing

This article will walk you through how to upload files in Django. We will create a simple application with a simple form to fill in details and select a file. Also, display all the uploaded files in a table underneath.

Before we proceed, it’s recommended to create a new folder or directory for this project to keep things organized.

Set the Django Environment

For this tutorial, we will use a virtual environment. It’s not compulsory to use a virtual environment, but it’s a good practice to have a unique virtual environment for every project.

To build a virtual environment, we need a Python package, virtualenv. If you don’t have it on your machine, you can download it using the following command.

pip install virtualenv

Now that you’ve installed the package, let’s create the environment.

To create an environment, run the following command.

virtualenv environment

environment is the name of the virtual environment we just created. This environment will have the Python version installed globally on your machine and no packages except the default ones.

To activate this environment and use it, run the following command.

environment\Scripts\activate

Now, since we are learning about Django, we need the Django library installed. Also, since we are learning to upload files, we need an additional Python package to deal with the images. The package name is Pillow. Let’s install all the dependencies.

pip install django
pip install Pillow

Or,

pip3 install django
pip3 install Pillow

Note that at the time of writing this article, the latest Django version is 3.2.

Setup Django Project

To set up a Django project, we first have to create a Django project, create an application, register that application, and make the initial migrations.

To create a Django project, run the following command.

django-admin startproject DjangoFileUpload

Now, change the working directory to this project using the following command.

cd DjangoFileUpload

To create an application inside the Django project, run the following command.

django-admin startapp Core

Or,

python manage.py startapp Core

Core is the name of the application.

To register this application, enter the application’s name inside the list INSTALLED_APPS in the settings.py file.

  • settings.py
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    "Core" # Here
]

Django needs a few models to work properly. For example, the authentication system or superuser won’t work without the initial migration. So, to make the initial migrations, run the following command.

python manage.py migrate

Output:

Operations to perform:
  Apply all migrations: admin, auth, contenttypes, sessions
Running migrations:
  Applying contenttypes.0001_initial... OK
  Applying auth.0001_initial... OK
  Applying admin.0001_initial... OK
  Applying admin.0002_logentry_remove_auto_add... OK
  Applying admin.0003_logentry_add_action_flag_choices... OK
  Applying contenttypes.0002_remove_content_type_name... OK
  Applying auth.0002_alter_permission_name_max_length... OK
  Applying auth.0003_alter_user_email_max_length... OK
  Applying auth.0004_alter_user_username_opts... OK
  Applying auth.0005_alter_user_last_login_null... OK
  Applying auth.0006_require_contenttypes_0002... OK
  Applying auth.0007_alter_validators_add_error_messages... OK
  Applying auth.0008_alter_user_username_max_length... OK
  Applying auth.0009_alter_user_last_name_max_length... OK
  Applying auth.0010_alter_group_name_max_length... OK
  Applying auth.0011_update_proxy_permissions... OK
  Applying auth.0012_alter_user_first_name_max_length... OK
  Applying sessions.0001_initial... OK

Test the Server

To run the server, use the following command. If everything went on error-free, you should see your Django server running at http://127.0.0.1:8000/.

python manage.py runserver

Update settings.py File

The uploaded files need to be stored somewhere. In Django, by default, all the uploaded files are stored in a media folder. You can always change the folder’s name and the URL associated with it, but we will stick to the default naming convention.

To define the URL to the media files, MEDIA_URL, and the path to the media folder, MEDIA_ROOT, add the following statements in the settings.py file.

  • settings.py
import os 

MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')

Don’t forget to import the os module. Otherwise, Python will throw an error.

Create a Model

To store the uploaded files, we have to create a model. The field in this model will hold the path to the uploaded file but not the file itself.

We will create a model Document to store the details about the uploaded files.

  • Core\models.py
from django.db import models

class Document(models.Model):
    title = models.CharField(max_length = 200)
    uploadedFile = models.FileField(upload_to = "Uploaded Files/")
    dateTimeOfUpload = models.DateTimeField(auto_now = True)

The model has a title field of a character type to store a custom title for the uploaded file, and dateTimeOfUpload will store the date and time of file upload. The date-time field would be automatically set when the model object is created.

To store the files, we are using FileField(). This type covers all sorts of files. But if you wish to be a bit specific with images, you can use the ImageField() to store the images. For all the other fields, you have to stick to FileField().

The upload_to parameter is used to define the folder, where the files of this model will be uploaded inside to media folder.

Before we use this model, we have to make migrations and migrate them. For that, run the two following commands.

python manage.py makemigrations
python manage.py migrate

Create a Form to Upload Files

Inside the Core application or folder, create a new folder, namely, templates. Inside this folder, create another folder, namely, Core. This should be the name of your application. Lastly, make a new file inside this folder, namely, upload-file.html.

Now you should have a file structure like this.

DjangoFileUpload/
    DjangoFileUpload/
        __init__.py
        asgi.py
        settings.py
        urls.py
        wsgi.py
    db.sqlite3
    manage.py
    Core/
        migrations/
        templates/
            Core/
                upload-file.html
        __init__.py
        admin.py
        apps.py
        models.py
        tests.py
        views.py

Inside the upload-file.html, add the following HTML.

  • Core\templates\Core\upload-file.html
<!DOCTYPE html>
{% load static %}
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Django File Upload</title>
    <style>
        @import url('https://fonts.googleapis.com/css2?family=Roboto&display=swap');

        * {
            font-family: "Roboto";
        }

        body {
            background-color: #F5F5F5;
        }

        form {
            background-color: #FFFFFF;
            padding: 25px;
        }

        table {
            width: 100%; 
            text-align: center;
            margin-top: 25px;
            padding: 25px;
            background-color: #FFFFFF;
        }

        table tr td {
            padding-top: 15px;            
        }
    </style>
</head>
<body>
    <form action="{% url 'Core:uploadFile' %}" method="POST" enctype="multipart/form-data">
        <input type="text" name="fileTitle" placeholder="Enter a title">
        <input type="file" name="uploadedFile">
        {% csrf_token %}
        <input type="submit" value="Upload">
    </form>
    <table>
        <tr>
            <th>ID</th>
            <th>Title</th>
            <th>File Path</th>
            <th>Upload Date & Time</th>
        </tr>
        {% for file in files %}
            <tr>
                <td>{{ file.id }}</td>
                <td>{{ file.title }}</td>
                <td>{{ file.uploadedFile.url }}</td>
                <td>{{ file.dateTimeOfUpload }}</td>
            </tr>
        {% endfor %}
    </table>
</body>
</html>

Inside the table, we will display some details about the uploaded files.

Add Views

To display the HTML template and information on it and store and handle the file uploads, we will create a view uploadFile().

Refer to the following code

  • Core\views.py
from . import models
from django.shortcuts import render

def uploadFile(request):
    if request.method == "POST":
        # Fetching the form data
        fileTitle = request.POST["fileTitle"]
        uploadedFile = request.FILES["uploadedFile"]

        # Saving the information in the database
        document = models.Document(
            title = fileTitle,
            uploadedFile = uploadedFile
        )
        document.save()

    documents = models.Document.objects.all()

    return render(request, "Core/upload-file.html", context = {
        "files": documents
    })

This view renders the HTML template we just created in the previous section. The form in the HTML template is submitted to the same URL and handled in this view. If the request’s method is POST, we fetch the information entered in the form and the file uploaded, store that information in the model and save the model.

Otherwise, in the general case, we fetch all the files that were uploaded and send them in a context dictionary to display on the HTML template.

Configure the urls.py File

Lastly, let’s set up the URLs. Before we proceed, create a new file, namely, urls.py inside the Core application or folder. This file will hold all the URLs associated with this Django application. It’s a good practice to have a separate urls.py file for every Django application.

Inside this file, add the following code.

from . import views
from django.urls import path
from django.conf import settings
from django.conf.urls.static import static

app_name = "Core"

urlpatterns = [
    path("", views.uploadFile, name = "uploadFile"),
]

if settings.DEBUG: 
    urlpatterns += static(
        settings.MEDIA_URL, 
        document_root = settings.MEDIA_ROOT
    )

We have added a URL pattern for the HTML template upload-file.html. Also, we have added one more URL for the media files. We will use the constant variables we declared in the settings.py file.

Since we created a new urls.py file inside the Core application, we have to link the URLs defined here with the main project.

To do that, add the following statement inside the urlpatterns list in DjangoFileUpload\urls.py

path("", include("Core.urls")),

Your file should look something like this.

File: DjangoFileUpload\urls.py

from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path("", include("Core.urls")),
]

Testing

Congratulations! Now it’s time to test the project. Follow the steps below.

  • Start the server using the command - python manage.py runserver
  • Go to the URL http://127.0.0.1:8000/
  • Fill the form with a title, select a file, and submit the form.

Now you should see some details about the file in the table underneath the form.

Moreover, if you’ll check your working directory, you’ll see that a folder by the name of media has been created, and inside this folder, there is another folder by the name of Uploaded Files. This folder contains all the uploaded files.

You can upload photos, videos, programs, PDFs, JSON files, HTML files, etc. Note that the uploading time depends on the size of the file, so have patience when uploading.

Contribute
DelftStack is a collective effort contributed by software geeks like you. If you like the article and would like to contribute to DelftStack by writing paid articles, you can check the write for us page.