Django Notes
Django Notes
Django
#Setting up project
(i) What is Virtual Environment in python?
For example, if you have two projects—one based on Machine Learning and
another on Django—each project will require different dependencies and
modules. Instead of installing all these dependencies globally, you can
create a separate virtual environment for each project. This allows you to
install only the required dependencies for each project within its own
environment, promoting separation of concerns and avoiding conflicts
between packages.
Django 1
(ii) Setting up vs code!
Download Django extension in vscode
materialicons extension
django-admin help
django-admin startproject project_name and then change the main top level
folder project_name to src
cd src
Django 2
folder named your project. (small app within our django app)
settings.py file contains all the settings for our django app for example
allowed host defines on which application our django application must be
served. Installed app section inisde which we defines what all are
applications that ccomes together to create our django app. Middlewares
section defines all the middlewares that comes between request and
response. Templating that allows you to embed dynamic data into your
static html pages.
urls.py → defines all of the urls or paths on the application that are
accessible.
django.contrib.auth
Django 3
#Basics
python manage.py startapp main
All Apps you created must be linked inside the installed app section of
settings.py file inside your main app.
(i)Django App
→ Migrations in Django are a way to save and apply changes you make to
your database tables.
For example, if you add a new field to a model (like a new column in a table), a
migration will record that change and update the database for you.
So, migrations help keep your Python models and your database structure in
sync.
📁 admin.py
You register your models here so they show up in the admin dashboard.
📁 apps.py
📁 models.py
This is where you define your database tables using Python classes.
Django 4
Example:
class Book(models.Model):
title = models.CharField(max_length=100)
📁 views.py
This is where you write what should happen when a user visits a page.
It connects the URL to the logic or the HTML page.
Example:
def home(request):
return render(request, 'home.html')
📁 tests.py
It’s like checking that your code is doing what it's supposed to.
Example:
def test_homepage(self):
response = self.client.get('/')
self.assertEqual(response.status_code, 200)
They take a request (like someone clicking a link) and return a response (like an
HTML page, some data, or a message).
Django 5
//views.py (inside main app)
Django 6
def main_view(request):
return HttpResponse("<h1>Welcome to CarVibe!</h1>")
urlpatterns = [
path('',main_view , name='main')
]
urlpatterns = [
path("admin/", admin.site.urls),
path('', include(main_app_urls))
Django 7
//main.html (inside views folder inside templates folder)
Django 8
# Create your views here.
def main_view(request):
return render(request,"views/main.html" ,{"name:" "Carvibe"})
STATIC_URL = '/static/'
Example structure:
myproject/
├── myapp/
│ └── static/
│ └── myapp/
│ └── styles.css
└── static/
└── global.css
#****************************************************************#
Django 9
At the top of your template ( .html ) file, add:
{% load static %}
🧱 4. {% extends 'base.html' %}
This tells Django that your current template inherits from another template
(usually a base layout).
🧩 5. {% block %}
This defines sections of content that can be filled in or overridden in child
templates.
{% load static %}
<!DOCTYPE html>
<html lang="en" class="h-100">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="">
<meta name="author" content="Hussain Mustafa, Preneure">
{% block title %}
<title>AutoMax . List Your Car Today!</title>
{% endblock %}
Django 10
<!-- Custom Style CSS -->
<link href="{% static 'css/style.css' %}" rel="stylesheet">
{% if messages %}
{% for message in messages %}
<div {% if message.tags %} class="alert alert-{{ message.tags }}" {% en
{{ message }}
</div>
{% endfor %}
{% endif %}
{% block header %}
<header class="p-3 bg-dark text-white w-100 nav-masthead">
<div class="container">
<div class="d-flex flex-wrap align-items-center justify-content-center
<a href="" class="d-flex align-items-center mb-2 mb-lg-0 text-white
<img class="bi me-2" width="32" height="32" src="{% static 'ima
</a>
{% if request.user.is_authenticated %}
<ul class="nav col-12 col-lg-auto me-lg-auto mb-2 justify-content-c
<li>
<a href="" class="nav-link px-2">Profile</a>
</li>
</ul>
<div class="text-end">
<a type="button" href="" class="btn btn-danger">Logout</a>
</div>
{% endif %}
</div>
</div>
Django 11
</header>
{% endblock %}
{% block footer %}
<footer class="footer mt-auto text-muted bg-dark py-5">
<div class="container">
<p class="float-end mb-1">Powered by <a href="https://www.djangop
<p class="mb-1">AutoMax - Best Place To Buy & Sell Cars</p>
<p class="mb-0">© Copyright {% now 'Y' %} <a href="">AutoMax</a
</div>
</footer>
{% endblock %}
</body>
</html>
{% extends 'base.html' %}
{% block content %}
<h1>Welcome to the Home Page!</h1>
<p>This is some content for the home page.</p>
{% endblock %}
Django 12
#Authentication
(i) Creating a users app and registering it inside
settings.py file inside mainapp
python manage.py startapp users
creating a profile model to extend features or add more details about users
in admin pannel.
def __str__(self):
return f'{self.user.username}\'s Profile'
Django 13
(iii) Registering the model to Django admin so that it
is accessible from admin pannel
#whatever functionality model admin allows profile admin will also allow those
class ProfileAdmin(admin.ModelAdmin):
pass
admin.site.register(Profile,ProfileAdmin)
Django 14
For example:
Instead of adding this code manually every time, you can use a signal that
says:
👉 "Hey! A new user was just saved — now go create their profile."
//signals.py inside users folder
# Import the 'post_save' signal — this is triggered right after a model is sav
from django.db.models.signals import post_save
# Import the built-in User model — we want to listen for when a new user i
from django.contrib.auth.models import User
# Only run the code below if a new user was just created
if created:
# Automatically create a Profile for the new user
# Connects the Profile to this user using a one-to-one relationship
Profile.objects.create(user=instance)
Django 15
//__init__.py
# users/apps.py
from django.apps import AppConfig
class UsersConfig(AppConfig):
name = 'users'
def ready(self):
import users.signals # <-- This is where signals are usually connected
✅ What it does:
It tells Django which AppConfig class to use when setting up the app.
🔍 Breaking it down:
'users.apps.UsersConfig' is the path to your custom AppConfig class.
# users/apps.py
from django.apps import AppConfig
class UsersConfig(AppConfig):
name = 'users'
def ready(self):
import users.signals # <-- This is where signals are usually connected
Most often, it's used to import and register signals (like the one you wrote).
def __str__(self):
return f'Location {self.id}'
Django 17
def __str__(self):
return f'{self.user.username}\'s Profile'
#whatever functionality model admin allows profile admin will also allow those
class ProfileAdmin(admin.ModelAdmin):
pass
class LocationAdmin(admin.ModelAdmin):
pass
admin.site.register(Profile,ProfileAdmin)
admin.site.register(Location,LocationAdmin)
#When user objects gets saved in the database run the below function
#each user inside the database is a instance
@receiver(post_save,sender=User)
def create_user_profile(sender,instance,created ,**kwargs):
if created:
Profile.objects.create(user=instance)
Django 18
(VI) Automating Location using signals
(lcoation automatically gets created whever user is created)
//signals.py
from .models import Profile , Location
from django.db.models.signals import post_save
from django.dispatch import receiver
from django.contrib.auth.models import User
#When user objects gets saved in the database run the below function
#each user inside the database is a instance
@receiver(post_save,sender=User)
def create_user_profile(sender,instance,created ,**kwargs):
if created:
Profile.objects.create(user=instance)
@receiver(post_save,sender=Profile)
def create_profile_location(sender,instance,created ,**kwargs):
if created:
profile_location = Location.objects.create()
instance.location = profile_location
instance.save()
Django 19
MEDIA_URL ='/media/'
def user_directory_path(instance,filename):
return 'user_{0}/{1}'.format(instance.user.id , filename)
"""
URL configuration for carvibe project.
The `urlpatterns` list routes URLs to views. For more information please see:
https://docs.djangoproject.com/en/5.2/topics/http/urls/
Examples:
Function views
1. Add an import: from my_app import views
2. Add a URL to urlpatterns: path('', views.home, name='home')
Class-based views
1. Add an import: from other_app.views import Home
2. Add a URL to urlpatterns: path('', Home.as_view(), name='home')
Including another URLconf
1. Import the include() function: from django.urls import include, path
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
"""
urlpatterns = [
path("admin/", admin.site.urls),
path('', include(main_app_urls))
Django 20
]
if settings.DEBUG:
urlpatterns+= static(settings.MEDIA_URL,document_root=settings.MEDIA_RO
def __str__(self):
return f'Location {self.id}'
Django 21
bio = models.CharField(max_length=140,blank=True)
phone_number = models.CharField(max_length=12, blank=True)
location = models.OneToOneField(Location, on_delete=models.SET_NULL ,
def __str__(self):
return f'{self.user.username}\'s Profile'
def login_view(request):
return render(request , 'views/login.html')
//inside users app folder create templates folder and inside it create views
folder and inside it create login.html
Django 22
{% extends 'base/base.html' %}
{% block body %}
<h1>Login View</h1>
{% endblock %}
{% block footer %}
<h1>Footer</h1>
{% endblock %}
urlpatterns=[
path('login/',login_view , name='login')
]
→Part 1
//views.py inside users app
def login_view(request):
Django 23
login_form = AuthenticationForm()
return render(request , 'views/login.html',{'login_form': login_form})
{% extends 'base/base.html' %}
{% load static %}
{% load crispy_forms_tags%}
{% block body %}
<div class="text-center">
<main class="form-signin">
<form action="" method="post">
<img class="mb-4" src="{% static 'images/logo.png' %}" alt="" width
{{ login_form | crispy}}
<button class="w-100 btn btn-lg btn-danger" type="submit">Sign In</
<p class="mt-5 mb-3 text-muted">Copyright © 2022 AutoMax</p>
</form>
</main>
</div>
{% endblock %}
{% block footer %}
{% endblock %}
INSTALLED_APPS = [
"django.contrib.admin",
"django.contrib.auth",
"django.contrib.contenttypes",
"django.contrib.sessions",
"django.contrib.messages",
"django.contrib.staticfiles",
"localflavor",
'crispy_forms',
'crispy_bootstrap5',
Django 24
"main",
"users",
]
→ Part 2
//views.py inside users app
def login_view(request):
if request.method == 'POST':
login_form = AuthenticationForm(request=request, data=request.POST)
if login_form.is_valid():
username = login_form.cleaned_data.get('username')
password = login_form.cleaned_data.get('password')
user = authenticate(username=username,password=password)
if user is not None:
pass
else:
pass
elif request.method=='GET':
login_form = AuthenticationForm()
return render(request , 'views/login.html',{'login_form': login_form})
Django 25
{% extends 'base/base.html' %}
{% load static %}
{% load crispy_forms_tags%}
{% block body %}
<div class="text-center">
<main class="form-signin">
<form action="" method="post">
<img class="mb-4" src="{% static 'images/logo.png' %}" alt="" width
{% csrf_token %}
{{ login_form | crispy}}
<button class="w-100 btn btn-lg btn-danger" type="submit">Sign In</
<p class="mt-5 mb-3 text-muted">Copyright © 2022 AutoMax</p>
</form>
</main>
</div>
{% endblock %}
{% block footer %}
{% endblock %}
#Important Info
→ 🔍 Django Filters (in templates):
Filters are used to modify or format data in Django templates.
Example:
{{ name|upper }}
JOHN
Django 26
✅ Common filters:
upper → makes text uppercase
→ 🔒 CSRF Token:
CSRF stands for Cross-Site Request Forgery. It’s a security feature.
Django uses a CSRF token to protect forms from being submitted by hackers
or fake sites.
When you make a form that sends data (like login or signup), you must include
this:
<form method="POST">
{% csrf_token %}
<!-- form fields -->
</form>
#Logging User in
//src/main/views.py
def main_view(request):
return render(request,"views/main.html",{"name":"CarVibe"})
Django 27
#ensuring that home view is accessible only whn user is logged in
@login_required
def home_view(request):
return render(request , "views/home.html")
//src/main/urls.py
urlpatterns = [
path('', main_view, name='main'),
path('home/',home_view,name='home')
]
//src/users/views.py
def login_view(request):
if request.method== 'POST':
login_form = AuthenticationForm(request=request , data=request.POST)
if login_form.is_valid():
username = login_form.cleaned_data.get('username')
password = login_form.cleaned_data.get('password')
user = authenticate(username=username, password=password)
if user is not None:
login(request,user)
return redirect('home')
else:
pass
elif request.method == 'GET':
Django 28
login_form = AuthenticationForm()
return render(request,'views/login.html',{'login_form': login_form})
/src/main/templates/views/home.html
{% extends 'base/base.html' %}
{%load static%}
{% block 'title' %}
<title>CarVibe Home</title>
{% endblock %}
{% block 'body' %}
<main>
<h1>{{request.user.username}}</h1>
</main>
{% endblock %}
/settings.py
LOGIN_URL = '/login/'
LOGIN_REDIRECT_URL = '/home/'
#Django Messages
In Django, messages refer to a framework used to send temporary, one-time
notifications (like alerts, success messages, or errors) to users — often after a
form is submitted or an action is performed.
Django 29
/settings.py
MESSAGE_TAGS = {
messages.ERROR:'danger'
}
/src/users/views.py
def login_view(request):
if request.method== 'POST':
login_form = AuthenticationForm(request=request , data=request.POST)
if login_form.is_valid():
username = login_form.cleaned_data.get('username')
password = login_form.cleaned_data.get('password')
user = authenticate(username=username, password=password)
if user is not None:
login(request,user)
messages.success(request,f'You are now logged in as {username}')
return redirect('home')
else:
messages.error (request, f'An error occured trying to login!')
else:
messages.error (request, f'An error occured trying to login!')
elif request.method == 'GET':
login_form = AuthenticationForm()
return render(request,'views/login.html',{'login_form': login_form})
/src/main/templates/base/base.html
Django 30
{%load static%}
<!DOCTYPE html>
<html lang="en" class="h-100">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="description" content="A short, accurate description of your w
<meta name="robots" content="index, follow" />
{% block 'title' %}
<title>CarVibe . List Your Car Today!</title>
{% endblock %}
</head>
<body>
{% if messages %}
{% endif %}
Django 31
{% block 'body' %}
{% endblock %}
</body>
{% block 'footer' %}
<footer class="footer text-muted bg-dark py-5 ">
<div class="container">
<p class="float-end mb-1">Powered by <a href="https://www.djangopro
<p class="mb-1">CarVibe - Best Place to Buy and Sell Cars</p>
</div>
</footer>
{% endblock %}
</html>
def register_view(request):
register_form = UserCreationForm()
return render(request,'views/register.html',{'register_form': register_form})
/src/users/templates/views/register.html
{% extends 'base/base.html' %}
{% load static %}
{% load crispy_forms_tags %}
Django 32
{% block 'body' %}
<div class="text-center">
<main class="form-signin">
<form action="" method="post">
<img class="mb-4" src="{% static 'images/logo.png' %}" alt="" width
{% csrf_token %}
{{ register_form |crispy }}
<button class="w-100 btn btn-lg btn-danger" type="submit">Register<
<p class="mt-5 mb-3 text-muted">Copyright © 2025 CarVibe</p>
</form>
</main>
</div>
{% endblock %}
{% block 'footer' %}
{% endblock %}
/src/users/urls.py
urlpatterns = [
path('login/',login_view, name='login'),
path('register/',register_view, name='register'),
Django 33
from django.views import View
class RegisterView(View):
def get(self, request):
register_form = UserCreationForm()
return render(request , 'views/register.html',{'register_form':register_form}
/src/users/urls.py
urlpatterns = [
path('login/',login_view, name='login'),
path('register/',RegisterView.as_view(), name='register'),
class RegisterView(View):
def get(self, request):
register_form = UserCreationForm()
return render(request , 'views/register.html',{'register_form':register_form}
Django 34
login(request, user)
messages.success(
request, f'User {user.username} registered successfully.')
return redirect('home')
else:
messages.error(request, f'An error occured trying to register.')
return render(request, 'views/register.html', {'register_form': register_fo
/src/main/templates/views/main.html
{% extends 'base/base.html' %}
{% load static %}
{% block 'body' %}
<div class="d-flex h-100 text-center text-white index">
<video autoplay muted loop id="myVideo">
<source src="{% static 'videos/bg.mp4' %}" type="video/mp4">
<!-- Credit: https://www.pexels.com/@kelly-l-1179532 (Pexels.com)-->
</video>
<div class="d-flex w-100 h-100 p-3 mx-auto flex-column main-content">
<header class="mb-auto">
<div>
<h3 class="float-md-start mb-0">CarVibe</h3>
<nav class="nav nav-masthead justify-content-center float-md-end
{% if request.user.is_authenticated %}
<a class="nav-link active" aria-current="page" href="{% url 'hom
{% else %}
<a class="nav-link" href="{% url 'login' %}">Login</a>
{% endif %}
</nav>
</div>
</header>
<main class="px-3">
<h2>Find a deal near you!</h2>
<p class="lead">Looking to buy or sell a used car? We've got you
covered. </br> CarVibe is the leading used car marketplace.</p>
Django 35
<p class="lead">
<a href="{% url 'register' %}"
class="btn btn-lg btn-secondary fw-bold border-white bg-white">
</p>
</main>
<footer class="mt-auto text-white-50">
<p>Copyright © {% now 'Y' %} <a href="" class="text-white">CarVibe
class="text-white">tejth</a></p>
</footer>
</div>
</div>
{% endblock %}
{% block 'footer' %}
{% endblock %}
@login_required
def logout_view(request):
logout(request)
return redirect('main')
/src/users/urls.py
urlpatterns = [
path('login/',login_view, name='login'),
path('register/',RegisterView.as_view(), name='register'),
Django 36
path('logout/' , logout_view , name='logout'),
]
/src/main/templates/base/base.html
<div class="text-end">
<a type="button" href="{% url 'logout' %}" class="btn btn-danger">Logout<
</div>
import re
from django import forms
class ListingForm(forms.ModelForm):
image = forms.ImageField()
class Meta:
model = Listing
fields = {'brand', 'model', 'vin', 'mileage',
'color', 'description', 'engine', 'transmisson', 'image'}
/src/main/templates/views/list.html
{% extends 'base/base.html' %}
{% load static %}
{% load crispy_forms_tags %}
{% block 'body' %}
<div class="container-fluid text-center py-5">
Django 37
<div class="container px-4 py-5" id="hanging-icons">
<div class="row g-4">
<div class="col d-flex align-items-start">
<div>
<h2 class="mb-3 border-bottom" style="color: black">List</h2>
</div>
</div>
</div>
<form action="" method="post" enctype="multipart/form-data">
{% csrf_token %}
<div class="row">
<div class="col-6">
{{listing_form|crispy}}
</div>
<div class="col-6">
{{location_form|crispy}}
</div>
</div>
<button class="btn btn-lg btn-danger" type="submit">Save</button>
</form>
</div>
</div>
{% endblock %}
import django_filters
Django 38
class ListingFilter(django_filters.FilterSet):
class Meta:
model = Listing
fields = {'transmisson': ['exact'], 'brand': [
'exact'], 'model': ['icontains'], 'mileage': ['lt']}
/main/views.py
@login_required
def home_view(request):
listings = Listing.objects.all()
listing_filter = ListingFilter(request.GET, queryset=listings)
user_liked_listings = LikedListing.objects.filter(
profile=request.user.profile).values_list('listing')
liked_listings_ids = [l[0] for l in user_liked_listings]
context = {
'listing_filter': listing_filter,
'liked_listings_ids': liked_listings_ids,
}
return render(request, "views/home.html", context)
/main/home.html
{% extends 'base/base.html' %}
{%load static%}
{% load crispy_forms_tags %}
{% block 'title' %}
<title>CarVibe Home</title>
{% endblock %}
{% block 'body' %}
<main>
Django 39
<section class="py-5 container">
<div class="row py-lg-5">
<div class="col-lg-6 col-md-8 mx-auto">
<h1 class="fw-light">CarVibe</h1>
<p class="lead text-muted">The best place to buy or sell modern ent
made it that much easier.</p>
<a href="{% url 'list' %}" class="btn btn-primary my-2">List Your Car
</div>
<div class="col-lg-6 col-md-8 mx-auto">
<form method="get">
{{ listing_filter.form|crispy }}
<button class="btn btn-sm btn-danger" type="submit">Submit</bu
</form>
</div>
</div>
</section>
<div class="album py-5 bg-light">
<div class="container">
<div class="row row-cols-1 row-cols-sm-2 row-cols-md-3 g-3">
{% for listing in listing_filter.qs %}
<div class="col">
{% include "components/listing_card.html" %}
</div>
{% endfor %}
</div>
</div>
</div>
</main>
{% endblock %}
# urls.py
from django.urls import path
from . import views
urlpatterns = [
path('car/<int:car_id>/', views.car_detail, name='car_detail'),
]
# views.py
def car_detail(request, car_id):
return HttpResponse(f"Car ID is {car_id}")
/car/7/ → car_id = 7
Common converters:
Converter Description
int Matches integers
str Matches any string
slug Matches slug strings (letters, numbers, dashes)
uuid Matches UUIDs
path Like str , but allows /
/search/?q=BMW
Django 41
# views.py
def search(request):
query = request.GET.get('q')
return HttpResponse(f"Searching for: {query}")
Summary:
Type Example URL Access in View
Django 42
profile=request.user.profile).all()
user_form = UserForm(request.POST, instance=request.user)
profile_form = ProfileForm(
request.POST, request.FILES, instance=request.user.profile)
location_form = LocationForm(
request.POST, instance=request.user.profile.location)
if user_form.is_valid() and profile_form.is_valid() and location_form.is_valid
user_form.save()
profile_form.save()
location_form.save()
messages.success(request, 'Profile Updated Successfully!')
return redirect('profile')
else:
messages.error(request, 'Error Updating Profile!')
return render(request, 'views/profile.html', {'user_form': user_form,
'profile_form': profile_form,
'location_form': location_form,
'user_listings': user_listings,
'user_liked_listings': user_liked_listings, })
class UserForm(forms.ModelForm):
username = forms.CharField(disabled=True)
class Meta:
model = User
fields = ('username', 'first_name', 'last_name', 'email')
class ProfileForm(forms.ModelForm):
photo = forms.ImageField(widget=CustomPictureImageFieldWidget)
bio = forms.TextInput()
class Meta:
model = Profile
fields = ('photo', 'bio', 'phone_number')
Django 43
#Custom Form Widget
🧩 What is a Custom Form Widget in Django?
In Django, a form widget is the part of the form responsible for rendering HTML
input elements like <input> , <select> , <textarea> , etc.
A custom form widget allows you to:
class CustomTextInput(forms.TextInput):
def __init__(self, *args, **kwargs):
kwargs.setdefault('attrs', {}).update({'class': 'custom-input', 'placehold
er': 'Enter text...'})
super().__init__(*args, **kwargs)
2. Using it in a form
Django 44
class MyForm(forms.Form):
name = forms.CharField(widget=CustomTextInput())
This renders:
Want to go further?
You can even override:
#Environment Variable
🌍 What are Django Environment Variables?
Environment variables in Django are used to keep sensitive or environment-
specific information (like secrets, database passwords, or debug flags) outside
of your source code.
Instead of hardcoding values in settings.py , you load them from a .env file or your
system's environment. This keeps your code secure, portable, and clean.
Django 45
pip install django-environ
# .env
SECRET_KEY=your-very-secret-key
DEBUG=True
DATABASE_NAME=mydb
DATABASE_USER=myuser
DATABASE_PASSWORD=mypass
3. 🧠 Update settings.py
Add this at the top of settings.py :
import environ
import os
from pathlib import Path
BASE_DIR = Path(__file__).resolve().parent.parent
# Initialize environment
env = environ.Env(
DEBUG=(bool, False)
)
# Use variables
SECRET_KEY = env('SECRET_KEY')
DEBUG = env('DEBUG')
Django 46