In this post, we will continue to learn Django by building a simple category manager application. This will give you a generalized view of how Django works as a whole.
Introduction
In this category manager app, we will have the following views
- index view – displays all the categories in the table.
- detail view – permalink page for a single entry.
- add category action – handles posting category.
- edit category action – handle edit of existing category.
- delete category – delete a category
In Django, web pages are delivered by views. Each view is represented by a Python function (or method, in the case of class-based views).
For the sake of this tutorial we will use function-based views. Django maps the respective views based on the URL.
Setup Django Project (Category Manager)
Let’s start by creating a new project mysite
. If you do not have prior knowledge of setting up a new project please follow my previous post i.e. Getting Started with Django.
Step 1: Create a new project
#terminal:
(myenv)$ python manage.py startapp categories
Step 2: Setup a database and a model
Add, categories in INSTALLED_APPS
in setting.py
to migrate the tables in database
#settings.py
...
INSTALLED_APPS = [
...
'categories',
]
...
Note: if you are using MySQL or Postgres, change database attributes in setting.py
.
#categories/models.py
from django.db import models
class Categories(models.Model):
name = models.CharField(max_length=200)
description = models.TextField()
def __str__(self):
return self.name
Each class in models.py
represents a table. Each field is specified as a class attribute, and each attribute maps to a database column.
#terminal
(myenv)$ python manage.py makemigrations
(myenv)$ python manage.py migrate

Step 3: Admin setup
Create superuser
#terminal
$ python manage.py createsuperuser
Add a username and password to login admin panel via http://127.0.0.0:8000/admin
Register model in Admin panel
#categories/admin.py
from django.contrib import admin
from .models import Categories
admin.site.register(Categories) #register categories in admin panel
This will provide the basic CRUD functionality in the admin panel. (Add few categories)

Step 4: Create a template for general user
First, create a directory called templates in your categories directory. Django will look for templates in there.
Within the templates directory that you have just created, create another directory called categories. Inside this folder, that create a file called index.html.
In other words, your template should be at categories/templates/categories/index.html.
Note: Your project’s TEMPLATES
settings describe how Django will load and render templates.
The default settings file configures a DjangoTemplates backend whose APP_DIRS
option is set to True.
By convention DjangoTemplates looks for a “templates” subdirectory in each of the INSTALLED_APPS
.
This app will contain four templates: index.html
, detail.html
, add.html
and edit.html
as:
#categories/index.htm
<!DOCTYPE html>
<html>
<head><title>index</title></head>
<style>
table{
border: 2px solid black;
border-collapse: collapse;
width: 50%;
}
th, td {
border: 1px solid black;
padding: 5px;
text-align: center;
}
th {
background-color: lightgrey;
}
</style>
<body>
<h1>List of Categories</h1>
<a href="{% url "categories:add" %}">Add</a> <br/><br/>
<table>
<thead>
<tr>
<th>Name</th>
<th>View</th>
<th>Edit</th>
<th>Delete</th>
</tr>
</thead>
<tbody>
{% for category in all_categories %}
<tr>
<td>{{ category.name }}</td>
<td><a href="{% url "categories:detail" category.id %}">view</a></td>
<td><a href="{% url "categories:edit" category.id %}">edit</a></td>
<td><a href="{% url "categories:delete" category.id %}">delete</a></td>
</tr>
{% endfor %}
</tbody>
</table>
</body>
</html>
#categories/detail.html
<h2>{{ category.name }}</h2>
<p> {{ category.description }}</p>
#categories/add.html
<h2>New Category</h2>
<form method="POST">{% csrf_token %}
<table>
{{ form.as_table }}
</table>
<button type="submit">Save</button>
</form>
#categories/edit.html
<h2>Edit Category</h2>
<form method="POST">{% csrf_token %}
<table>
{{ form.as_table }}
</table>
<button type="submit">Save</button>
</form>
The add.html
and edit.html
files contain forms for which modelForms
in used.
Step 5: Add a forms.py file
Add a forms.py
file inside categories application to render a model form in template.
#forms.py
from django.forms import ModelForm
from .models import Categories
class CategoryForm(ModelForm):
class Meta:
model = Categories
fields = ('name', 'description',)
It will generate a form tags with respective name in templates
Step 6: Write views for respective functionalities.
Each view is responsible for returning an HttpResponse
object containing the content for the requested page, or raising an exception such as Http404
.
#categories/views.py
from django.shortcuts import get_object_or_404, render
from django.shortcuts import redirect
from .models import Categories
from .forms import CategoryForm
def index(request):
all_categories = Categories.objects.all() #retrive all categories
context = {'all_categories': all_categories}
return render(request, 'categories/index.html', context)
def detail_category(request, pk):
category = get_object_or_404(Categories, pk=pk) #retrive single category
return render(request, 'categories/detail.html', {'category': category})
#create
def new_category(request):
if request.method == "POST":
form = CategoryForm(request.POST)
if form.is_valid():
category = form.save(commit=False)
category.save()
return redirect('categories:detail', pk=category.pk)
else:
form = CategoryForm()
return render(request, 'categories/add.html', {'form': form})
#update
def edit_category(request, pk):
category = get_object_or_404(Categories, pk=pk)
if request.method == "POST":
form = CategoryForm(request.POST, instance=category)
if form.is_valid():
category = form.save(commit=False)
category.save()
return redirect('categories:detail', pk=category.pk)
else:
form = CategoryForm(instance=category)
return render(request, 'categories/edit.html', {'form': form})
#delete
def delete_category(request, pk):
category = get_object_or_404(Categories, pk=pk)
category.delete()
return redirect('categories:index')
In views.py, index(request)
function retrieves all the categories and renders those categories in index.html template. Similarly, detail(request, pk)
retrieves only a single category which is mapped from urls.py and render the category in detail.html template.
new_category(request)
uses a modelform to render the form in the add.html template and save the user data in the database. Similarly, edit_category(request, pk)
uses the modelform to render edit.html template and edit a specific category which is mapped from URL.
delete(request, pk)
function deletes a category from the database.
step 7: write URLs to maps respective views functions.
add a new file called urls.py in categories application directory
#categories/urls.py
from django.urls import path
from . import views
app_name = 'categories'
urlpatterns = [
path('', views.index, name='index'),
path('add', views.new_category, name='add'),
path('<int:pk>/', views.detail_category, name='detail'),
path('edit/<int:pk>/', views.edit_category, name='edit'),
path('delete/<int:pk>', views.delete_category, name='delete'),
]
Note: these path maps the urls to their respective views.
Also include the app URLs in project URLs
#mysite/urls.py
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('category/', include('categories.urls'))
]
Now you can view the existing categories via http://127.0.0.1:8000/category/ by starting development server
#terminal
(myenv)$ python manage.py runserver

(index.html)
Wrapping Up
In this post, we created a simple category manager where we learned CRUD operations i.e. Create, Retrieve, Update, and Delete in Django.
In the next post, we will add functionality to disable/hide categories from public view in this application.
You must be logged in to post a comment.