Let’s Django! — First Steps into Django Web Development

Merin George
10 min readMay 13, 2021

Looking for a hassle-free way to get started with your brand-new web project? Sick of PHP and all its drivel? Here’s a robust framework that lets you focus on the fun parts of coding without dealing with the torment that web development brings along. Django is quite undeniably an amalgamation of elegance, readability, versatility and flexibility. It has significantly grown to be one of the most wanted MVC-based web frameworks in recent years.

In this tutorial, we’d like to show you how to get your first-ever Django project up and running from scratch. Hope you have as much fun as we did while working on it.

Before you get started, it is integral to have a basic knowledge of Python and OOPs concepts.

Requirements:

  • Python 3.x.x
  • Django 3.2.2 (you can use any newer version as long as they don’t change the entire framework)

Getting started

One of the best ways to learn how to use a framework is to get your hands dirty and create a quick application. We shall learn how to use Django by building a simple ‘to-do list’ app with basic CRUD operations.

Let’s begin by installing Django.

Open your Terminal or Command Prompt and type the following command which will install Django and any packages required by it:

pip install django

Note: Installing Django in a virtual environment is much safer as newer versions of Django or any other packages you use may break your project. Though this isn’t a mandatory step, it is much recommended.

Now, let us create our first Django project. Navigate to the location where you want to install the project and type the following command:

django-admin startproject mysite

You can change the name of the project by replacing ‘mysite’ in the command.

Our new project folder will look like this:

New Project

We can test our project by running the following command:

python manage.py runserver

We then open the link given in the terminal (generally it is http://127.0.0.1:8000/).

First Screen

Yay, our Django project is running.

Creating an app

In Django, every module in your project can be separated into smaller Django apps. This is great as you can create individual apps to handle each module which will make it easy to debug your code or to reuse apps for new projects. For our ‘to-do list’ project, let’s create an app with the name ‘todo’ by using the following command:

python manage.py startapp todo

You can change the name of the app by replacing ‘todo’ with the name you want.

Our project folder will now look like this:

Project Folder after installing the ‘todo’ app

Now, go to the settings.py file and add the name of the app into the installed apps list:

INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'todo', # <--- this is what we're adding to the list
]

Our app is ready to go!

Creating a model

A model in Django is basically like the structure of a database. We can have a separate model for each application with its own set of tables (defined as python classes). Django saves these models in the database as normal tables. The default Django database adapter is SQLite but we can change the adapter to use any other database system.

Let’s set up our models in the models.py file.

from django.db import modelsclass Task(models.Model):
name = models.CharField(max_length=50)
is_completed = models.BooleanField(default=False)
def __str__(self):
return self.name
  • First, we import the Django models from the database package.
  • We define the table by creating a class ‘Task’ and we add ‘models.Model’ to notify that this is a Django model.
  • We will create two attributes — ‘name’ stores the task name, defined as a character field with a max length of 50 characters, while ‘is_completed’ is used to see if the task is completed and it is defined as a Boolean with a default value ‘False’.
  • You can learn more about different Django fieldtypes in the official documentation on this page.
  • def __str__() is used to give a string representation to the object.

Now that we’re done defining our models, we have to tell Django about these changes.

python manage.py makemigrations todo

Let’s apply our generated migrations by using the following command:

python manage.py migrate todo

Admin

An admin account will allow us to create, alter or delete any records in our database. This is very useful to manage the data that is stored and also display and modify any records that are hidden from a regular user.

To create an admin account, simply use the following command:

python manage.py createsuperuser

This will ask you for a username, email and password (Psst. email is optional, just leave it blank if you want to skip it).

Now, we have to register our model for it to show up on our admin page. Go to the admin.py file and enter the following code:

from django.contrib import admin
from .models import Task
admin.site.register(Task)

Let’s run the server and go to the following location http://127.0.0.1:8000/admin/ on your browser. Login with your credentials to view the admin page.

Django Admin Page

Note: Remember that you can quit the server by pressing CTRL+C.

Creating URLs and Views

In the MVC model, the Controller is used to tell the framework what views to render and the Views are responsible for rendering the front-end of our application.

In Django, we use the URLs as the controller. We use a variable named ‘urlpatterns’ which has the list of URLpath instances. Each ‘urlpattern’ contains the URL, the corresponding view it renders and a name that we can use to call the pattern from a webpage.

Now, we’ll add a URL to our home page.

Enter the following code in the urls.py file in your project folder:

from django.conf.urls import include
from django.contrib import admin
from django.urls import path
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('todo.urls', namespace='todo'))
]

Here, we are importing and making use of the include function. This allows us to call the ‘urlpatterns’ that we will set in each individual app. This allows us to have an individual app’s URLs to be defined in the app itself.

Let’s set the ‘urlpatterns’ for our todo app.

Enter the following code in the urls.py file in your app folder:

from django.urls import path
from . import views
app_name = 'todo'urlpatterns = [
path('', views.task_list, name='task_list'),
]

Before we dive into this code, let’s set up our views in the views.py file in the app folder:

from django.shortcuts import render
from .models import Task
def task_list(request):
tasks = Task.objects.all()
return render(request, 'task_list.html', {'tasks': tasks})

Here, we are importing the render, redirect and get_object_or_404 which we will be using later. In the render function, we are setting our template to an HTML file that will be rendered when this function is called. If we look at the urls.py file, we see that with the path ‘ ’ (generally represented as ‘/’), the ‘task_list’ view is rendered. Remember to import the views at the beginning of your urls.py file.

Templates

Templates are HTML files that will be used to render the front-end of our project. These files are usually stored in the templates folder inside each app.

Let’s create a web page called ‘task_list.html’ file by adding these lines:

<!DOCTYPE html>
<html>
<head>
<title>Todo App</title>
</head>
<body>
<div>
<ul>
{% if tasks %}
{% for task in tasks %}
{% if tasks.is_completed %}
<li class="checked">{{ task.name}}</li>
{% else %}
<li>{{ task.name}}</li>
{% endif %}
{% endfor %}
{% else %}
<li>No Tasks</li>
{% endif %}
</ul>
</div>
</body>
</html>
  • First, we check if there are any tasks present in the database. If there are no tasks present, ‘No tasks’ will be displayed instead.
  • If there are items in the database, we will use a ‘for loop’ to go through each item in the list. We only need to define the code for one item and the loop will set it for all items on the list.
  • We check if the task is completed by checking the ‘is_completed’ value. If it is, we will print the task item with the CSS class ‘checked’.
  • {{ task.name }} is used to print the data in the name attribute.
  • Finally, we end our conditional statements by using {% endfor %} and {% endif %} statements.

To get our Django project to identify the templates, we must include the name of the directory in the template section of our settings.

Modify the settings.py file with the following code:

TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': ['templates'], # <--- we put the folder name here
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]

Forms

To accept input from the user, we use forms.

There are two different types of web requests that can be used for forms. A GET request, which is generally used to open a particular page (GET data from the database) and a POST request, which is generally used to send data to the server to manipulate the database (POST data to the database).

Let’s create a form that accepts a new task from the user.

Create a new file named ‘forms.py’ in your todo folder and add the following lines:

from django import forms
from .models import Task
class TaskForm(forms.ModelForm):
class Meta:
model = Task
fields = ['name']

We must import the model and set what fields are to be entered by the user. Now, we can simply call the form by adding the following lines into our task_list.html file:

<form method="post">
{% csrf_token %}
{{ inputForm }}
<span>
<input class="addBtn" type="submit" value="Add" />
</span>
</form>

Let’s modify our views to accept a new task and save it to the database. Remember to import the ‘TaskForm’ into the views.py file.

from .forms import TaskFormdef task_list(request):
tasks = Task.objects.all()
if request.method == 'POST':
taskform = TaskForm(request.POST)
if taskform.is_valid():
taskform.save()
inputForm = TaskForm()
return render(request, 'task_list.html', {'tasks': tasks, 'inputForm': inputForm})

In the view, we check if the request method is POST. We receive the inputs from ‘request.POST’ and check if the form is valid. If it is, the data is saved into the database. An empty form is set to the variable ‘inputform’ and is sent to the template just like the tasks data.

Now, we’re all set to add tasks into our app!

Updating and Deleting our Tasks

In order to update or delete our tasks, we need to identify the single task object from the list of objects in our database. For this, we use the ‘pk’ value. ‘pk’ is simply a primary key that Django sets for all objects by default. Some people may override it by using a different attribute, but we’re going to use ‘pk’.

Let’s create a new view that updates the task to be completed. We obtain the ‘pk’ value from the argument and use it to get the object with that ‘pk’. ‘get_object_or_404’ is used to get the task object or return a 404 indicating it is not found. Since we’re using the ‘is_completed’ attribute to check if the task is completed or not, we can simply update the value by setting it to ‘True’ and saving it to the database. After saving, the view will redirect to the main page.

def update_task(request, pk):
task = get_object_or_404(Task, pk=pk)
if request.method == 'POST':
task.is_completed = True
task.save()
return redirect('/')

We can create another view for deleting a task by simply calling task.delete().

def delete_task(request, pk):
task = get_object_or_404(Task, pk=pk)
if request.method == 'POST':
task.delete()
return redirect('/')

Let’s put both of these views to the ‘urlpatterns’ list. We need to include the ‘pk’ argument in the URL so that we can send the ‘pk’ value.

from django.urls import path
from . import views
app_name = 'todo'urlpatterns = [
path('', views.task_list, name='task_list'),
path('update/<pk>', views.update_task, name='update_task'),
path('delete/<pk>', views.delete_task, name='delete_task'),
]

Now, we modify our task_list.html file with a button that we can use to set our task as ‘Completed’ and another button to delete it. We have to wrap each button inside a form and set the action to go to the URL we’ve specified along with the task’s ‘pk’ value. The urls.py will call the appropriate view function. We’re also going to add some extra CSS code to make it look good.

{% for task in tasks %}

{% if task.is_completed %}
<form action="delete/{{ task.pk }}" method="post">
{% csrf_token %}
<li class="checked">
{{ task.name }}
<span><button type="submit">Delete</button></span>
</li>
</form>

{% else %}

<li>
<div class="Row">
<div class="Column">{{ task.name }}</div>
<span style="float: right;">
<div class="Column">
<form action="update/{{ task.pk }}" method="post">
{% csrf_token %}
<button type="submit">
Mark as completed
</button>
</form>
</div>
<div class="Column">
<form action="delete/{{ task.pk }}" method="post">
{% csrf_token %}
<button type="submit">
Delete
</button>
</form>
</div>
</span>
</div>
</li>
{% endif %}
{% endfor %}

Finally, save your files and run the server to see the results.

Final Application

And with that, we have completed our ‘to-do list’ app.

Though we only covered the basic operations, Django is very versatile and can be used to build huge projects without worrying about writing database queries, middleware connections, etc. Django also has its own user management system which can handle creating, updating and deleting users with ease. Additionally, it has a plethora of both python and Django-specific packages that can be used to reduce unnecessary coding and allows the user to concentrate on creating a visually appealing and functional site.

Do check out Django’s official documentation to understand more functions and features of the framework.

The full source code of this application along with the CSS code that we didn’t include is available on the GitHub repository linked here.

P.S. If you face any problems, remember that Google is your best friend.

Written by Akash Roshan, Merin Mariyam George and Kriya Dudi Sanju

--

--