Django – How to upload, view, delete file using ModelForm and MySQL


In this tutorial, we’re gonna look at way to upload file in Django using Django ModelForm and save its information to MySQL Database. We also have UI to view list of uploaded items and function to delete specific file.

Related Post: Simple way to upload file in Django

Project Overview

What we will do

We will create a Django Application that allows us to upload files, images and more information corresponding to a data model: Tutorial(title,category,feature_image,attachment).


We can also view the list of all uploaded items and have ability to delete item that we want to remove.


All files (attachments, feature images) will be stored in filesystem, the data model information (title, category, file url) will be saved to MySQL database.


Project Structure

There are several folders and files in our Django project:

django-upload-file-model-form-example-mysql-project-structure contains settings for media path, template & static folder directory. with urlpatterns.
tutorials/ defines functions to handle HTTP request.
tutorials/ defines Tutorial model with FileField and ImageField.
tutorials/ defines ModelForm for Tutorial model.
templates is the template for upload form and list view.

Django Project to upload, view, delete file using ModelForm

Setup Django project
Create project

Create Django project named DjangoUploadModelForm with command:
django-admin startproject DjangoUploadModelForm

Install & Import Python MySQL Client

We have to install Python MySQL Client to work with MySQL database.
In this tutorial, we use pymysql: pip install pymysql.

Once the installation is successful, import this module in DjangoUploadModelForm/

import pymysql

Setup MySQL Database engine

Open DjangoUploadModelForm/ and change declaration of DATABASES:

   'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'testdb',
        'USER': 'root',
        'PASSWORD': '123456',
        'HOST': '',
        'PORT': '3306',
Create Django App

Run following commands to create new Django App named tutorials:
cd DjangoUploadModelForm
python startapp tutorials

Open tutorials/, we can see TutorialsConfig class (subclass of the django.apps.AppConfig) that represents our Django app and its configuration:

from django.apps import AppConfig

class TutorialsConfig(AppConfig):
    name = 'tutorials'

This Django App will be used to upload, view and delete tutorials.

Add Django App to Django project

Open gkzRestApi/, find INSTALLED_APPS, then add:

    # Tutorials application 
Configure path for uploaded files

In project’s, set value for MEDIA_ROOT and MEDIA_URL:
+ MEDIA_ROOT: Absolute filesystem path to the directory that holds uploaded files.
+ MEDIA_URL: url for media (uploaded files) from MEDIA_ROOT.

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

So uploaded files will be accessed with root url /files/..., and they are located at folder named files.

Implement Data Model
Create Data Model

Our Tutorial data model is a Django Model with 4 fields: title, category, feature_image, attachment.

To handle uploaded files, we use model fields: FileField for attachment and ImageField for feature_image.


from django.db import models

class Tutorial(models.Model):
    title = models.CharField(max_length=100)
    category = models.CharField(max_length=100)
    feature_image = models.ImageField(upload_to='tutorial/images/')
    attachment = models.FileField(upload_to='tutorial/attachments/')

    def __str__(self):
        return self.title

    def delete(self, *args, **kwargs):
        super().delete(*args, **kwargs)

FileField or ImageField will not help us store file/image in the database but in the filesystem. upload_to parameter specifies where the file/image will be stored. In the code, feature_image will be save to files/tutorial/images folder, and attachment will locate at files/tutorial/attachments. ('files' was indicated by MEDIA_ROOT).

If you want to create more folders for datetime, you can use:
doc = models.FileField(upload_to='docs/%Y/%m/%d/')
The uploaded file will be located at MEDIA_ROOT/files/docs/2019/03/15 for example.

FileField and ImageField are saved as a string field in database that will be references to the real files/images. So we need to override Django Model delete() method, it helps us handle removing actual file/image from storage. If we don’t do this, ONLY Tutorial information (title, category, file info) will be deleted from database, all files still exist.

Run initial migration for data model

Run following Python script:
python makemigrations tutorials

We can see output text:

Migrations for 'tutorials':
    - Create model Tutorial

It indicates that the tutorials/migrations/ file includes code to create Tutorial data model:

# Generated by Django 2.1.7 on 2019-03-15 03:42

from django.db import migrations, models

class Migration(migrations.Migration):

    initial = True

    dependencies = [

    operations = [
                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                ('title', models.CharField(max_length=100)),
                ('category', models.CharField(max_length=100)),
                ('feature_image', models.ImageField(upload_to='tutorial/images/')),
                ('attachment', models.FileField(upload_to='tutorial/attachments/')),

The generated code defines a subclass of the django.db.migrations.Migration. It has an operation for creating Tutorial model table. Call to migrations.CreateModel() method will create a table that allows the underlying database to persist the model.

Run the following Python script to apply the generated migration:
python migrate tutorials

The output text:

Operations to perform:
  Apply all migrations: tutorials
Running migrations:
  Applying tutorials.0001_initial... OK

Check MySQL Database, now we can see that a table for Tutorial model was generated and it’s named tutorials_tutorial:


Create ModelForm for Data Model

Under tutorials app folder, create new file named

from django import forms

from .models import Tutorial

class TutorialForm(forms.ModelForm):

    class Meta:
        model = Tutorial
        fields = ['title', 'category', 'feature_image', 'attachment']

This form maps closely to Tutorial model that we’ve created before. fields attribute indicates the order of form fields specified by model field.

For more details about form field that is corresponding of each model field, please visit list of conversions.

Handle upload, view, delete request

Inside tutorials/, define some functions:

tutorialList(): get list of Tutorials from database, render list.html template.

uploadTutorial(): get form data from HTTP POST request, save form data to database and files to filesystem storage, render list.html template if the process is successful. Otherwise, return to upload.html template.

deleteTutorial(): delete a Tutorial by its id (pk).

from django.shortcuts import render, redirect

from .forms import TutorialForm
from .models import Tutorial

def tutorialList(request):
    tutorials = Tutorial.objects.all()
    return render(request, 'tutorial/list.html', { 'tutorials' : tutorials})

def uploadTutorial(request):
    if request.method == 'POST':  
        form = TutorialForm(request.POST, request.FILES)
        if form.is_valid():
            return redirect('tutorial_list')
        form = TutorialForm()
    return render(request, 'tutorial/upload.html', {'form' : form})

def deleteTutorial(request, pk):
    if request.method == 'POST':
        tutorial = Tutorial.objects.get(pk=pk)
    return redirect('tutorial_list')

We can get form data simply just by assigning request.FILES to the file field of TutorialForm. Then, calling will save file object to the 'upload_to' location of FileField/ImageField (defined in Tutorial data model).

Add templates
Create template with form submission

Under project root folder, create templates folder, then create tutorial/upload.html file insides:

ozenero upload Tutorial

{% csrf_token %} {{ form.as_p }}

The form is submitted via POST method, and the submitted file will be placed in request.FILES.

We must use the attribute enctype="multipart/form-data" in HTML form. If not, request.FILES in views.upload(request) will be empty.

Create template for displaying list

Under templates folder, create tutorial/list.html file insides:

{% load static %}

ozenero Tutorials

Upload Tutorial {% if tutorials %} {% for tutorial in tutorials %} {% endfor %}
Feature Image Title Category Attachment Action
{{ tutorial.title }} {{ tutorial.category }} Download
{% csrf_token %}
{% endif %}

The template gets tutorials data from views and shows it in the table.
We also use a submit button inside a form with POST method to make a delete request to views.

Now we need place for css file.

Create static folder

Under project root folder, create static folder, then create css/tutorial.css file insides:

table {
  font-family: arial, sans-serif;
  border-collapse: collapse;
  width: 600px;

td, th {
  border: 1px solid #dddddd;
  text-align: left;
  padding: 5px;
Specify template & static directory

In project’s, set templates path for 'DIRS':

        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': ['templates'],
        'APP_DIRS': True,

Then add value for STATICFILES_DIRS:

    os.path.join(BASE_DIR, 'static'),
Set Url pattern

Now, we add path to urlpatterns and set up location for uploaded files:

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

from tutorials import views

urlpatterns = [
    path('tutorials/upload/', views.uploadTutorial, name='upload_tutorial'),
    path('tutorials/', views.tutorialList, name='tutorial_list'),
    path('tutorials/', views.deleteTutorial, name='tutorial'),

if settings.DEBUG:  # remember to set 'DEBUG = True' in
    urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

Source Code


0 0 votes
Article Rating
Notify of
Newest Most Voted
Inline Feedbacks
View all comments