Django Teaching Notes Documentation 2.o
Django Teaching Notes Documentation 2.o
0:
SECTION:I
**************
1. Django Overview
Introduction
Django is a powerful Python framework designed to streamline the process of building web
applications. It handles many of the complex tasks involved in web development, allowing
developers to focus on writing their apps rather than reinventing the wheel. Emphasizing the
principle of DRY (Don’t Repeat Yourself), Django promotes the reusability of components and
includes ready-to-use features like authentication systems, database connections, and CRUD
(Create, Read, Update, Delete) operations.
Django is both free and open source, built and maintained by a community of experienced
developers.
● Content Management Systems (CMS): Platforms like Django CMS and Wagtail offer
robust content management solutions, making it easier to manage web content.
● Social Networking Sites: Django powers parts of popular social networking platforms
like Instagram, managing user interactions, and content seamlessly.
● E-commerce Platforms: Sites like Pinterest and The Washington Times utilize
Django for its scalability and flexibility, handling the complexities of online retail
effectively.
● Educational Platforms: Django is the backbone of educational platforms like Udemy
and Khan Academy, managing course content, user accounts, and interactions.
● News Websites: News outlets such as The Guardian and Mozilla Foundation’s
Common Voice project rely on Django for content management and user engagement.
● Healthcare Applications: Django is used in healthcare apps for managing patient
records, scheduling appointments, and facilitating communication between healthcare
providers and patients.
● Government Websites: Various government agencies use Django to build websites and
applications that provide essential services and information to citizens.
● Data Analytics Platforms: Django is employed by data analytics platforms like Civis
Analytics for managing data, user authentication, and generating dynamic reports.
● Financial Services: Django powers web applications in the financial sector, supporting
online banking, financial planning, and investment management.
● Software as a Service (SaaS) Platforms: Many SaaS companies leverage Django for
its scalability, security, and ease of development to build core applications.
2. Django Installation
1. Isolation:
Virtual environments allow you to isolate the dependencies of one project from those of
another. This prevents conflicts between different projects that might require different
versions of the same package.
2. Dependency Management:
With virtual environments, you can install project-specific dependencies without affecting
the global Python installation. This ensures that your project uses the correct versions of
packages.
3. Reproducibility:
Virtual environments help ensure that your project is reproducible across different
environments. By specifying dependencies within the virtual environment, you can easily
recreate the environment on another machine, making it easier to collaborate with others
and deploy your project in production.
4. Cleanliness:
Virtual environments keep your global Python environment clean by isolating
project-specific dependencies. This helps avoid clutter and makes it easier to maintain a
tidy development environment.
Installation of a Virtual Environment
If you haven't already installed virtualenv, you can do so using pip, Python's package
manager. Open your terminal or command prompt and run the following command:
Open your terminal or command prompt and navigate to the directory where you want to create
the virtual environment. Use the cd command to change directories.
Once you're in the desired directory, run the following command to create a virtual environment
named myenv (you can replace myenv with any name you prefer):
“virtualenv myenv”
This command will create a new directory named myenv in your current directory, which
contains the isolated Python environment.
After creating the virtual environment, you need to activate it. Activation sets up your terminal or
command prompt to use the Python interpreter and packages installed within the virtual
environment. The activation command varies depending on your operating system:
● Windows:
myenv\Scripts\activate
macOS/Linux:
source myenv/bin/activate
You'll notice that your command prompt or terminal changes to indicate that you're now working
within the virtual environment, often by displaying the name of the environment at the beginning
of the prompt.
To deactivate the virtual environment and return to your global Python environment, simply run
the following command:
“deactivate”
Your command prompt or terminal will return to its normal state, indicating that you've exited the
virtual environment.
Installation of Django
It's a good practice to create a virtual environment for your Django projects to isolate their
dependencies. To create a virtual environment, use the following command:
Replace myenv with the name you want to give to your virtual environment.
● On Windows:
myenv\Scripts\activate
On macOS/Linux:
source myenv/bin/activate
Step 4: Install Django
Once your virtual environment is activated, you can use pip to install Django:
This command will download and install the latest version of Django along with its
dependencies.
You can verify that Django is installed correctly by running the following command:
This should display the installed Django version, confirming that it’s successfully installed.
To create a new Django project, you can use the following command:
● Replace projectname with the desired name for your Django project.
This command sets up the basic structure of a Django project, including essential directories
and files like manage.py (a command-line utility) and the project settings file.
● manage.py: A command-line utility that lets you interact with your Django project. You
can use it to run the development server, start new apps, and interact with the database.
● requirements.txt (optional): A file where you can list all the Python dependencies for
your project. This makes it easier to install them using pip.
Project Package
● This is a directory with the same name as your project, which contains the project's
settings and configuration files.
● init.py: An empty file that indicates this directory should be treated as a Python package.
● settings.py: Contains all the configuration settings for your Django project, including
installed apps, middleware, database settings, and more.
● urls.py: The URL configuration file where you map URL patterns to views. This file
defines the paths available in your project.
● wsgi.py: Used for deploying your project using a WSGI-compatible web server. WSGI
stands for Web Server Gateway Interface.
● asgi.py: Similar to wsgi.py, but used for deploying your project using an
ASGI-compatible web server. ASGI stands for Asynchronous Server Gateway Interface.
After creating your Django project, you can start the development server to see your application
in action. Navigate to your project's directory using the command line and run:
● This will start the development server on the default port 8000.
● You can access your Django application by opening a web browser and going to
http://127.0.0.1:8000/.
If you need to run the Django project on a different port, you can specify the port number like
this:
This practice ensures that all developers working on the project have a consistent
development environment.
Model-View-Controller (MVC)
● Model: Represents the data and business logic of the application. It handles data
manipulation, storage, and retrieval. The model interacts with the database and defines
how data is structured and managed.
● View: Represents the presentation layer. It displays the data to the user and serves as
the user interface. The view presents the data provided by the model in a format that the
user can understand.
● Controller: Acts as an intermediary between the model and the view. It handles user
input, processes it, and updates the model accordingly. The controller also updates the
view when the model changes. It is responsible for interpreting user actions (e.g., clicks,
form submissions) and invoking the appropriate responses.
● The controller is a crucial component that manages the flow of data between the model
and the view.
● MVC provides a clear separation of concerns, with the controller mediating between the
data (model) and the user interface (view).
● Commonly used in frameworks like Ruby on Rails, ASP.NET MVC, and Spring MVC.
Model-View-Template (MVT)
● Model: Similar to MVC, the model represents the data and business logic of the
application. It interacts with the database and defines how data is structured, validated,
and manipulated.
● View: Represents the presentation layer, similar to the view in MVC. However, in MVT,
the view is often more focused on processing and selecting data to be presented to the
user, leaving the rendering of data to the template.
● Template: Represents the structure of the user interface. Templates are typically HTML
files with placeholders for dynamic data. These placeholders are filled in by the view with
data from the model, allowing for the presentation of dynamic content.
● In MVT, there's no explicit controller component. Instead, the Django framework itself
handles the routing of requests and delegates tasks to the appropriate view.
● The template plays a central role in defining the structure and presentation of the user
interface, combining static HTML with dynamic content from the model.
● Django automatically manages the flow of control, making it easier to handle user
requests and responses without manually coding a controller.
Summary:
● MVC explicitly defines a controller component to manage the interaction between the
model and view. This separation is useful for larger, more complex applications where
you need granular control over user interaction.
● MVT, used in Django, abstracts away the need for a controller by letting the framework
handle request routing and view selection. The template in MVT is key to defining how
the data is presented, making it easier to manage the user interface and dynamic
content.
While both patterns promote modular architecture and separation of concerns, MVC offers more
explicit control over the flow of data and user interaction, whereas MVT simplifies development
by relying on the framework to manage these aspects.
The Django web framework follows the MVT pattern (Model-View-Template), a variation of the
MVC (Model-View-Controller) pattern. The MVT pattern is tailored to Django's design
philosophy and conventions, providing a streamlined and efficient way to develop web
applications. Below is an explanation of how Django implements the MVT structure:
1. Model
● Definition: In Django, the model represents the data structure and business logic of the
application. Models are typically defined as Python classes, where each class
corresponds to a table in the database. These classes define the fields and behaviors of
the data entities in the application.
● Object-Relational Mapping (ORM): Django's ORM allows developers to interact with
the database using Python objects, abstracting away the details of writing raw SQL
queries. This makes it easier to perform CRUD (Create, Read, Update, Delete)
operations and manage database relationships.
● Location: Models are defined in the models.py file within each Django app. For
example:
class Author(models.Model):
name = models.CharField(max_length=100)
birthdate = models.DateField()
2. View
● Definition: In Django, the view is responsible for handling user requests and generating
the appropriate response. Views are Python functions or classes that receive HTTP
requests, process them, and return HTTP responses.
● Interaction with Models: Views often interact with models to retrieve or manipulate data
before rendering a response. They serve as the intermediary between the model (data)
and the template (presentation).
● Types of Views: Django provides both function-based views (FBVs) and class-based
views (CBVs). FBVs are simpler and more straightforward, while CBVs offer more
structure and reusability through inheritance and mixins.
● Location: Views are defined in the views.py file within each Django app. For example:
def author_list(request):
authors = Author.objects.all()
return render(request, 'authors.html', {'authors': authors})
3. Template
● Definition: The template in Django represents the presentation layer of the application.
It defines the structure and layout of the HTML pages that are sent to the client.
Templates contain static parts of the desired HTML output as well as placeholders for
dynamic content.
● Django Template Language (DTL): Django templates use the Django Template
Language, which allows developers to embed logic like variables, loops, and
conditionals directly into HTML. This makes it easy to dynamically generate content
based on the data passed from the view.
● Location: Templates are typically stored in the templates directory within a Django
app. The template files usually have an .html extension. For example:
1. Request Handling: A user makes a request to a URL that is routed to a Django view.
2. View Processing: The view processes the request, interacts with the model layer to
fetch or manipulate data as necessary, and prepares the data to be displayed.
3. Template Rendering: The view renders a template, passing the processed data to it.
The template uses this data to generate an HTML page.
4. Response: The rendered HTML page is sent as a response to the user's browser,
where it is displayed.
Summary:
Django's MVT pattern emphasizes a clean separation of concerns, making it easier to manage
and maintain your web application. By leveraging Django's powerful ORM, flexible view system,
and dynamic templates, you can build robust and scalable web applications with minimal
boilerplate code.
5. Creating an Application in Django
Creating an app in Django is a fundamental step in building a modular and organized web
application. An app in Django is a self-contained module that can be reused across different
projects. Below are the steps to create and integrate an app into your Django project:
First, navigate to the directory of your Django project using the cd command. This ensures that
you’re working within the correct project context.
cd projectname
To create a new app within your Django project, use the following command. This will generate
the necessary directory structure and files for your app:
Replace appname with the name of your app. This command will create a directory structure
similar to the following:
appname/
__init__.py
admin.py
apps.py
migrations/
__init__.py
models.py
tests.py
views.py
Apps
● Django projects are organized into multiple applications (apps), each of which is a
self-contained module with its own functionality.
● Each app typically has the following structure:
○ models.py: Defines the data models for your app, which Django uses to create
database tables.
○ views.py: Contains the view functions or classes that process requests and
return responses.
○ urls.py: (Optional) Used for defining URL patterns specific to the app.
○ admin.py: Registers models with the Django admin site, allowing you to manage
them via a web interface.
○ apps.py: Contains the app configuration, which can include metadata and
settings specific to the app.
○ migrations/: A folder that contains migration files, which are used to alter the
database schema based on your models.
○ static/: A folder for storing static files like CSS, JavaScript, and images used by
the app.
○ templates/: A folder for storing HTML template files that are rendered by your
views.
○ tests.py: A file for writing tests to ensure your app functions as expected.
Next, you need to inform Django about your new app by adding it to the INSTALLED_APPS list
in your project’s settings.py file:
# projectname/settings.py
INSTALLED_APPS = [
# ...
'appname',
]
This step ensures that Django recognizes your app and includes it in the project.
4. Define Models
In your app’s models.py file, define the data models that your app will use. Django’s
Object-Relational Mapping (ORM) system allows you to define your data structure as Python
classes, which are automatically translated into database tables.
# appname/models.py
from django.db import models
class YourModel(models.Model):
field1 = models.CharField(max_length=100)
field2 = models.IntegerField()
def __str__(self):
return self.field1
5. Create Migrations
To create the necessary database migrations for your models, run the following command:
This command generates migration files that describe the changes you made to your models.
6. Apply Migrations
This will execute the migrations and update your database schema.
Now, you can start building the user interface and logic for your app:
● Views: Define the logic that handles user requests in your app’s views.py.
● Templates: Create HTML templates in a templates directory inside your app directory.
● URLs: Define the URL patterns for your app in urls.py.
# appname/views.py
from django.shortcuts import render
def homepage(request):
return render(request, 'homepage.html')
In urls.py:
# appname/urls.py
from django.urls import path
from . import views
urlpatterns = [
path('', views.homepage, name='homepage'),
]
In your project’s urls.py, include the URLs of your app using the include function:
# projectname/urls.py
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('appname/', include('appname.urls')), # Include app-specific URLs here
]
This step connects your app's URLs to the main project’s URL configuration.
Summary
You've now successfully created and integrated an app into your Django project. This process
includes setting up models, views, templates, and URLs. You can continue to develop your app
by adding more features, views, templates, and other functionalities as needed. By organizing
your project into separate apps, you maintain a clean and scalable codebase, making it easier
to manage and extend in the future.
A Django project is organized into a specific directory structure that helps manage different
components of the application efficiently. Below is an overview of the typical contents of a
Django project folder and the role each part plays.
1. manage.py:
○ Purpose: This is a command-line utility that interacts with your Django project. It
allows you to run development servers, create database tables, manage
applications, run tests, take backups of fixtures, create superusers, open Django
shells, and perform various other administrative tasks.
○ Common Commands:
■ python manage.py runserver — Start the development server.
■ python manage.py migrate — Apply database migrations.
■ python manage.py createsuperuser — Create an admin user.
■ python manage.py shell — Open an interactive Python shell.
Project Settings
The settings.py file in Django serves as the central configuration hub for the entire project.
Here’s an overview of the key settings found in this file:
1. Database Configuration:
○ Purpose: Defines the database connections for your project.
○ Commonly Configured Databases:
■ SQLite (default): Requires no additional configuration.
■ MySQL: Requires installation of mysqlclient (pip install
mysqlclient).
■ PostgreSQL: Requires installation of psycopg2 (pip install
psycopg2).
○ Parameters: To connect to databases like MySQL or PostgreSQL, you need to
specify additional parameters:
■ ENGINE, NAME, USER, PASSWORD, HOST, PORT.
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': 'mydatabase',
'USER': 'myuser',
'PASSWORD': 'mypassword',
'HOST': 'localhost',
'PORT': '5432',
}
}
Debug Mode:
Installed Apps:
● Purpose: Lists all the Django apps that are installed in your project.
● Example:
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'myapp', # Your custom app
]
Middleware:
● Purpose: Middleware classes process requests and responses globally before they
reach the view or after they leave the view.
● Common Middleware:
○ SecurityMiddleware
○ SessionMiddleware
○ CommonMiddleware
○ CsrfViewMiddleware
○ AuthenticationMiddleware
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
]
Static Files:
STATIC_URL = '/static/'
STATICFILES_DIRS = [
os.path.join(BASE_DIR, 'static'),
]
Template Configuration:
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'templates')],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
],
},
},
]
LANGUAGE_CODE = 'en-us'
TIME_ZONE = 'UTC'
USE_I18N = True
USE_L10N = True
USE_TZ = True
Security Settings:
1. Install Django
This will create a directory named helloworld with the basic Django project structure.
cd helloworld
python manage.py startapp myapp
This will create a new directory myapp within your project, where you'll build the "Hello World"
functionality.
Open the settings.py file located in the helloworld/helloworld directory and add
myapp to the INSTALLED_APPS list:
INSTALLED_APPS = [
...
'myapp',
]
5. Create a View
In myapp/views.py, create a simple view function that returns an HTTP response with "Hello,
World!":
def hello_world(request):
return HttpResponse("Hello, World!")
Create a urls.py file inside the myapp directory (if it doesn't already exist), and define a URL
pattern for your view:
urlpatterns = [
path('', views.hello_world, name='hello_world'),
]
Open the helloworld/urls.py file in the project directory and include the myapp URLs:
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('myapp.urls')), # Include the app's URL patterns
]
Open your web browser and go to http://127.0.0.1:8000/. You should see the text
"Hello, World!" displayed on the screen.
That's it! You've created a basic "Hello World" program in Django. This simple example shows
how to set up a Django project, create an app, and map a view to a URL.
In Django, customizing the user model allows you to extend or modify the default authentication
system to suit your application's needs.
A custom manager allows you to define methods for creating users, including additional logic or
constraints. Although optional, it's often a good practice to define a custom manager when
working with a custom user model.
class CustomUserManager(BaseUserManager):
def create_user(self, email, password=None, **extra_fields):
if not email:
raise ValueError('The Email field must be set')
email = self.normalize_email(email)
user = self.model(email=email, **extra_fields)
user.set_password(password)
user.save(using=self._db)
return user
def create_superuser(self, email, password=None, **extra_fields):
extra_fields.setdefault('is_staff', True)
extra_fields.setdefault('is_superuser', True)
Subclass the AbstractUser class to create your custom user model. In this example, we'll use
the email field as the unique identifier for authentication instead of the username.
class CustomUser(AbstractUser):
email = models.EmailField(unique=True)
# Add any additional fields you want here
objects = CustomUserManager()
def __str__(self):
return self.email
● The email field is set to be unique, ensuring that each user has a distinct email
address.
● The username field is removed, and email is used as the USERNAME_FIELD for
authentication.
● REQUIRED_FIELDS is left empty because we only require the email and password for
user creation.
Connecting the Custom User Model to the Admin Panel:
After defining the custom user model, make sure to update your settings.py to use it:
AUTH_USER_MODEL = 'yourappname.CustomUser'
This line tells Django to use your custom user model instead of the default one.
Once we have done with the customized user model lets us see how to create a user signup
and login view for that.
To create a signup and login functionality using Django with two different views, you can follow
these steps:
First, create a view that allows users to sign up by providing their email and password.
def signup_view(request):
if request.method == 'POST':
form = UserCreationForm(request.POST)
if form.is_valid():
form.save()
messages.success(request, "Account created successfully. You can now log in.")
return redirect('login') # Redirect to the login page after successful signup
else:
form = UserCreationForm()
Next, create a view that allows users to log in using their email and password.
from django.shortcuts import render, redirect
from django.contrib.auth import authenticate, login
from django.contrib import messages
def login_view(request):
if request.method == 'POST':
email = request.POST['email']
password = request.POST['password']
user = authenticate(request, username=email, password=password)
if user is not None:
login(request, user)
messages.success(request, "You have successfully logged in.")
return redirect('home') # Redirect to the homepage or dashboard after
successful login
else:
messages.error(request, "Invalid email or password. Please try again.")
You will need to create simple HTML templates for signup and login forms. Here are basic
examples:
signup.html
<!DOCTYPE html>
<html>
<head>
<title>Sign Up</title>
</head>
<body>
<h2>Sign Up</h2>
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Sign Up</button>
</form>
<p>Already have an account? <a href="{% url 'login' %}">Login here</a></p>
</body>
</html>
Login.html:
<!DOCTYPE html>
<html>
<head>
<title>Login</title>
</head>
<body>
<h2>Login</h2>
<form method="post">
{% csrf_token %}
<label for="email">Email:</label>
<input type="email" name="email" required><br><br>
<label for="password">Password:</label>
<input type="password" name="password" required><br><br>
<button type="submit">Login</button>
</form>
<p>Don't have an account? <a href="{% url 'signup' %}">Sign up here</a></p>
</body>
</html>
4. Update urls.py
Finally, add URL patterns for the signup and login views in your app's urls.py:
urlpatterns = [
path('signup/', signup_view, name='signup'),
path('login/', login_view, name='login'),
]
5. Customizing UserCreationForm (Optional)
If you're using a custom user model with an email field, you might want to customize the
UserCreationForm to include the email field instead of the default username. Here's an
example:
class CustomUserCreationForm(UserCreationForm):
email = forms.EmailField(required=True)
class Meta:
model = get_user_model()
fields = ("email",)
def signup_view(request):
if request.method == 'POST':
form = CustomUserCreationForm(request.POST)
if form.is_valid():
form.save()
messages.success(request, "Account created successfully. You can now log in.")
return redirect('login')
else:
form = CustomUserCreationForm()
Django provides various ways to generate HTTP responses based on the requirements of your
application. Below are some common response types that you might use in Django:
I) HttpResponse
The most straightforward way to generate an HTTP response in Django is by using the
HttpResponse class. This class allows you to create an HttpResponse object with the
content you want to send as the response. You can also set HTTP headers and status codes as
needed.
Example:
def my_view(request):
response = HttpResponse("Hello, World!", content_type="text/plain")
response.status_code = 200
response['Custom-Header'] = 'Header Value'
return response
In this example:
Often, you'll want to render HTML templates and return them as responses. Django provides the
render function to simplify this process. You can define HTML templates using Django's
template language and then render them with context data to generate dynamic HTML.
Example:
In this example:
● The context dictionary is passed to the template, allowing you to insert dynamic
content.
When working with AJAX or building APIs, you may need to return JSON responses. Django's
JsonResponse class makes it easy to create JSON responses.
Example:
def json_view(request):
data = {'key': 'value'}
return JsonResponse(data)
def user_view(request):
user_data = list(User.objects.all().values())
return JsonResponse(user_data, safe=False)
In this example:
IV) Redirects
To redirect users to another URL, you can use the redirect function.
Example:
def redirect_view(request):
return redirect('new_url')
def redirect_urls(request):
return redirect("http://localhost:8080/token/userdetails")
V) TemplateResponse
Example:
def my_template_view(request):
context = {'name': 'John Doe'}
return TemplateResponse(request, 'my_template.html', context)
VI) FileResponse
FileResponse is used to serve files efficiently as HTTP responses. This is particularly useful
for serving large files, such as images, PDFs, or other downloadable content, as it streams the
file to the client without loading the entire file into memory.
def serve_image(request):
file_path = '/home/user/Pictures/shiva/shiva4.jpg'
response = FileResponse(open(file_path, 'rb'))
response['Content-Type'] = 'image/jpeg'
response['Content-Disposition'] = 'attachment; filename="shiva_pics.jpg"'
return response
In these examples:
● file_path should point to the location of the file you want to serve.
● Content-Type specifies the type of content being served.
● Content-Disposition suggests how the browser should handle the file, with
attachment indicating that the file should be downloaded rather than displayed inline.
1. Basic Response
The simplest way to return a response in DRF is by using the Response class from
rest_framework.response.
Example:
@api_view(['GET'])
def example_view(request):
data = {
'message': 'Hello, World!',
'status': 'success'
}
return Response(data)
In this example:
You can specify HTTP status codes using the status module from rest_framework.
Example:
@api_view(['POST'])
def create_item(request):
if request.method == 'POST':
# Perform creation logic here
data = {'message': 'Item created successfully'}
return Response(data, status=status.HTTP_201_CREATED)
else:
data = {'message': 'Invalid request method'}
return Response(data, status=status.HTTP_400_BAD_REQUEST)
In this example:
3. Custom Headers
Example:
@api_view(['GET'])
def custom_header_view(request):
data = {'message': 'Hello with custom headers'}
response = Response(data)
response['X-Custom-Header'] = 'Custom value'
return response
In this example:
DRF provides a way to handle errors gracefully using custom error responses.
Example:
@api_view(['GET'])
def item_detail(request, item_id):
try:
# Assume get_item is a function that retrieves an item by id
item = get_item(item_id)
data = {'item': item}
return Response(data)
except Item.DoesNotExist:
raise NotFound(detail="Item not found", code=404)
In this example:
● The NotFound exception is used to return a 404 response with a custom message.
5. Content Negotiation
DRF can return responses in different formats like JSON, XML, etc. The format is automatically
negotiated based on the client's request.
Example:
@api_view(['GET'])
def example_view(request):
data = {
'message': 'Hello, World!',
'status': 'success'
}
return Response(data)
In this example:
● The response format is determined by the Accept header in the client's request (e.g.,
application/json, application/xml).
When working with serializers, APIView allows for more complex operations with DRF.
Example:
class SampleView(APIView):
In this example:
Using Django Rest Framework (DRF) allows you to handle various HTTP methods (GET, POST,
PUT, PATCH, DELETE) in a simplified and structured way. Here’s an example:
Create a Model
class Book(models.Model):
title = models.CharField(max_length=100)
author = models.CharField(max_length=100)
published_date = models.DateField()
def __str__(self):
return self.title
Create a Serializer
Serializers in DRF are used to convert model instances into JSON format and vice versa:
class BookSerializer(serializers.ModelSerializer):
class Meta:
model = Book
fields = '__all__'
Using APIView
class BookListCreateView(APIView):
books = Book.objects.all()
return Response(serializer.data)
serializer = BookSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
class BookDetailView(APIView):
serializer = BookSerializer(book)
return Response(serializer.data)
book = Book.objects.get(pk=pk)
if serializer.is_valid():
serializer.save()
return Response(serializer.data)
book = Book.objects.get(pk=pk)
book.delete()
return Response(status=status.HTTP_204_NO_CONTENT)
Using ViewSets
class BookViewSet(viewsets.ModelViewSet):
queryset = Book.objects.all()
serializer_class = BookSerializer
Step 6: Configure URLs
To wire these views into your URLs, you need to update urls.py:
For APIView
urlpatterns = [
path('books/', BookListCreateView.as_view(), name='book-list-create'),
path('books/<int:pk>/', BookDetailView.as_view(), name='book-detail'),
]
router = DefaultRouter()
router.register(r'books', BookViewSet)
urlpatterns = [
path('', include(router.urls)),
]
Models:
In Django, models are a core component of the Object-Relational Mapping (ORM) system. They
define the structure of your application's database tables and provide an abstraction layer for
interacting with the database. Models allow you to work with data in a more Pythonic way, using
Python classes and objects instead of writing raw SQL queries.
Example:
class Person(models.Model):
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=30)
age = models.IntegerField()
In Django, each model field defines a column in the database table. Below is an overview of
common field types you can use in Django models:
CharField:
title = models.CharField(max_length=100)
TextField:
description = models.TextField()
IntegerField:
price = models.FloatField()
FloatField:
price = models.FloatField()
DateField:
birthdate = models.DateField()
TimeField:
appointment_time = models.TimeField()
DateTimeField:
created_at = models.DateTimeField(auto_now_add=True)
BooleanField:
is_active = models.BooleanField(default=True)
EmailField:
email = models.EmailField(max_length=100)
URLField:
website = models.URLField(max_length=200)
image = models.ImageField(upload_to='images/')
document = models.FileField(upload_to='documents/', null=True, blank=True)
ForeignKey:
AutoField:
id = models.AutoField(primary_key=True)
SlugField:
● A field for storing URL slugs, often used for SEO-friendly URLs.
● Example:
slug = models.SlugField(max_length=50)
BigIntegerField:
large_number = models.BigIntegerField()
PositiveIntegerField:
positive_number = models.PositiveIntegerField()
DecimalField:
OneToOneField:
ManyToManyField:
categories = models.ManyToManyField(Category)
JSONField:
metadata = models.JSONField()
Model Attributes:
In Django models, the @property decorator is often used to define dynamic, computed
attributes based on the model’s fields. These attributes are accessible like normal fields, but
their values are computed dynamically.
Example
class Person(models.Model):
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
birth_date = models.DateField()
@property
def full_name(self):
@property
def age(self):
Once defined, these properties can be accessed as if they were regular attributes of the model
instance.
Example Usage:
1. Encapsulation: Control access to an attribute and add logic to the getter method without
changing the interface.
2. Readability: Access methods like attributes, making the code more readable.
3. Dynamic Computation: Compute values dynamically based on other fields or logic.
By default, properties created with @property are read-only. If you try to assign a value to
them, an error will be raised:
In the example below, we define two models: Author and Book. The Book model has a foreign
key field author that establishes a one-to-many relationship with the Author model. This
means one author can be associated with multiple books, but each book is associated with only
one author.
class Author(models.Model):
name = models.CharField(max_length=100)
class Book(models.Model):
title = models.CharField(max_length=100)
books_by_author = author.book_set.all()
author_of_book = book.author
Book.objects.filter(id=2).values('author__name')
● Explanation: The author attribute in the Book model allows access to the Author
associated with a specific Book. The query with filter demonstrates how to retrieve
an author's name directly.
title = models.CharField(max_length=100)
class Author(models.Model):
name = models.CharField(max_length=100)
class Book(models.Model):
title = models.CharField(max_length=100)
authors = models.ManyToManyField(Author)
book.authors.add(author1, author2)
● Explanation: The add method associates multiple Author instances with a Book.
Retrieving Books by Authors
authors_of_book = book.authors.all()
● Explanation: You can filter books by an author's name and retrieve all authors
associated with a book.
book.authors.remove(author1)
● Explanation: The remove method removes the relationship between the Book and the
Author without deleting either.
genre_average_ratings =
Book.objects.filter(pub_date__gte="2020-01-01").values('genre').annotate(
average_rating=Avg('rating'),
book_count=Count('id')
Real-World Example
res1 =
OrganistaionUserRespondentResponse.filterAll(user_assessment__id__in=data["team_assess
ment_id"],
is_participant=True).values("assessment_question__attribute__attribute_name").annotate(rating
=Avg('assessment_value'))
● Explanation: This is a real-world query that aggregates ratings for different assessment
attributes.
One-to-One Relationships
from django.db import models
class Person(models.Model):
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=30)
class UserProfile(models.Model):
bio = models.TextField()
person = Person.objects.get(first_name="John")
user_profile = person.userprofile
person = user_profile.person
● Explanation: The one-to-one relationship allows easy access between Person and
UserProfile.
Querying Data:
people = Person.objects.filter(age__gt=25)
person = Person.objects.get(pk=1)
person.age = 31
person.save()
person.delete()
1. Creating Models
● Blog, Author, and Entry classes are defined in models.py using Django's
models.Model base class.
● Blog contains fields for name and tagline.
● Author contains fields for name and email.
● Entry contains fields like blog (ForeignKey to Blog), headline, body_text,
pub_date, mod_date, and a ManyToManyField authors linked to the Author model.
Creating Instances in Django Shell:
b1 = Blog.objects.create(name="xyz", tagline="testtag")
a1 = Author.objects.create(name="william")
e1 = Entry.objects.create(headline="williambook", blog=b1)
e1.authors.add(a1)
● Updating
e1.name = "elmname"
e1.save()
● Filtering
Entry.objects.filter(id=1).values()
Entry.objects.filter(name__startswith="elm").values()
Entry.objects.filter(name__endswith="me").values()
Entry.objects.filter(name__icontains="nam").values()
4. Date Filtering
import datetime
Entry.objects.filter(pub_date__gte=datetime.date.today()).values()
Entry.objects.filter(pub_date__lte=datetime.date.today()).values()
Entry.objects.all()[:2]
Entry.objects.all().order_by("name")
● Case-sensitive
Entry.objects.get(headline__contains="Lennon")
Case-insensitive
Entry.objects.filter(headline__icontains="lennon")
7. ForeignKey Filtering
Entry.objects.filter(blog__name="Beatles Blog")
Blog.objects.exclude(entry__headline__contains="Lennon",
entry__pub_date__year=2008)
Entry.objects.filter(number_of_comments__gt=F("number_of_pingbacks"))
Entry.objects.values("pub_date__year").annotate(
top_rating=Subquery(
Entry.objects.filter(pub_date__year=OuterRef("pub_date__year"))
.order_by("-rating")
.values("rating")[:1]
),
total_comments=Sum("number_of_comments"),
)
Blog.objects.get(pk=14)
class Dog(models.Model):
name = models.CharField(max_length=200)
data = models.JSONField(null=True)
Key and Path Transforms:
Dog.objects.filter(data__owner__name="Bob")
Dog.objects.filter(data__owner__other_pets__0__name="Fishy")
Caching in QuerySets
● QuerySets cache their results upon evaluation but are not cached when sliced or
indexed unless fully evaluated first.
queryset = Entry.objects.all()
print([p.headline for p in queryset]) # Caches the queryset
print(queryset[5]) # Uses cache
● KT (Key Transform) is used to work with JSON data keys and indexes in queries.
Dogs.objects.annotate(
first_breed=KT("data__breed__1"), owner_name=KT("data__owner__name")
).filter(first_breed__startswith="lhasa", owner_name="Bob")
Here are the revised notes on Django ORM queries, focusing on containment and key lookups,
as well as complex queries with Q objects:
contained_by Lookup
This is the inverse of the contains lookup. It returns objects where the key-value pairs on the
object are a subset of the value passed.
# Query dogs where the data is a subset of {"breed": "collie", "owner": "Bob"}
Dog.objects.filter(data__contained_by={"breed": "collie", "owner": "Bob"})
# Returns: [<Dog: Meg>, <Dog: Fred>]
has_key Lookup
This lookup returns objects where the given key exists in the top level of the JSONField.
has_any_keys Lookup
This lookup returns objects where any of the given keys are present in the top level of the
JSONField.
# Query dogs that have either "owner" or "breed" keys
Dog.objects.filter(data__has_any_keys=["owner", "breed"])
# Returns: [<Dog: Rufus>, <Dog: Meg>]
Q objects allow for more complex queries, such as using OR conditions or negating conditions.
# Query entries where question starts with "Who" and the publication date is not in 2005
Q(question__startswith="Who") | ~Q(pub_date__year=2005)
# Combined example
Poll.objects.get(
Q(question__startswith="Who"),
Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6)),
)
# Translates to SQL:
# SELECT * FROM polls WHERE question LIKE 'Who%' AND (pub_date = '2005-05-02'
OR pub_date = '2005-05-06')
# Query entries where question starts with "Who" and the publication date is not in 2005
Q(question__startswith="Who") | ~Q(pub_date__year=2005)
# Combined example
Poll.objects.get(
Q(question__startswith="Who"),
Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6)),
)
# Translates to SQL:
# SELECT * FROM polls WHERE question LIKE 'Who%' AND (pub_date = '2005-05-02' OR
pub_date = '2005-05-06')
start_date = date(2023, 1, 1)
end_date = date(2023, 12, 31)
start_date = date(2023, 1, 1)
end_date = date(2023, 12, 31)
Both methods will retrieve records where the date_field falls within the specified date range.
Here is an explanation of the Admin configuration for the Django admin panel:
Key Points:
This configuration ensures that the Address model is displayed in the admin panel with
enhanced usability, including custom email display, filtering, search, and ordering options.
Here are some advanced configurations and customizations you can explore to enhance the
Django admin panel:
1. Custom Actions
● You can define custom actions that can be applied to the selected records in the admin
panel.
class ProductAdmin(admin.ModelAdmin):
list_display = ('name', 'price', 'is_featured')
actions = [mark_as_featured]
admin.site.register(Product, ProductAdmin)
2. Inlines
● Inlines allow you to include related models within the admin interface of another model
class BookInline(admin.TabularInline):
model = Book
extra = 1
class AuthorAdmin(admin.ModelAdmin):
inlines = [BookInline]
admin.site.register(Author, AuthorAdmin)
3. Custom Forms
● You can customize the forms used in the admin panel by using custom form classes
class ProductAdminForm(forms.ModelForm):
class Meta:
model = Product
fields = ['name', 'price', 'description']
def clean_price(self):
price = self.cleaned_data.get('price')
if price < 0:
raise forms.ValidationError("Price cannot be negative")
return price
class ProductAdmin(admin.ModelAdmin):
form = ProductAdminForm
admin.site.register(Product, ProductAdmin)
● Django admin uses templates that can be overridden to customize the look and feel.
class MyAdmin(admin.ModelAdmin):
def get_urls(self):
urls = super().get_urls()
custom_urls = [
path('my_custom_view/', self.my_custom_view),
]
return custom_urls + urls
admin.site.register(Product, MyAdmin)
class SecureAdminSite(admin.AdminSite):
def has_permission(self, request):
return request.user.is_active and request.user.is_staff and
request.user.groups.filter(name='AdminGroup').exists()
admin_site = SecureAdminSite(name='secure_admin')
admin_site.register(User)
7. Custom Filters
class PriceFilter(admin.SimpleListFilter):
title = 'price'
parameter_name = 'price'
class ProductAdmin(admin.ModelAdmin):
list_filter = (PriceFilter,)
admin.site.register(Product, ProductAdmin)
● Use custom widgets in your admin forms for a better user experience
class ProductAdmin(admin.ModelAdmin):
formfield_overrides = {
models.CharField: {'widget': TextInput(attrs={'size': '20'})},
}
admin.site.register(Product, ProductAdmin)
These advanced configurations can significantly improve the usability, functionality, and security
of your Django admin panel.
The list_filter attribute allows you to add filters to the admin list view, making it easier to
search for specific records.
class YourModelAdmin(admin.ModelAdmin):
list_filter = ('field1', 'field2') # Replace with your actual field names
admin.site.register(YourModel, YourModelAdmin)
You can even filter based on related models by using the double underscore (__) syntax:
class BookAdmin(admin.ModelAdmin):
list_filter = ('author__name',) # Filter books by author's name
admin.site.register(Book, BookAdmin)
If your model has a foreign key, you can display the related model's fields using a custom
method in the list_display attribute.
class BookAdmin(admin.ModelAdmin):
list_display = ('title', 'get_author_name', 'published_date')
def get_author_name(self, obj):
return obj.author.name if obj.author else "N/A"
admin.site.register(Book, BookAdmin)
Use fieldsets to organize fields into sections in the admin form, making it more user-friendly.
class YourModelAdmin(admin.ModelAdmin):
fieldsets = (
('Basic Information', {
'fields': ('field1', 'field2'),
'description': 'This section contains basic fields.',
}),
('Advanced Options', {
'fields': ('field3', 'field4'),
'classes': ('collapse',), # Make this section collapsible
}),
)
admin.site.register(YourModel, YourModelAdmin)
Let's consider a model Product and demonstrate how to register and customize it in the
Django admin.
Model Definition:
class Product(models.Model):
name = models.CharField(max_length=100)
price = models.DecimalField(max_digits=10, decimal_places=2)
quantity = models.IntegerField()
category = models.ForeignKey('Category', on_delete=models.CASCADE)
def __str__(self):
return self.name
Admin Customization:
class ProductAdmin(admin.ModelAdmin):
list_display = ('name', 'price', 'quantity', 'get_category_name')
list_filter = ('category__name',)
get_category_name.short_description = 'Category'
admin.site.register(Product, ProductAdmin)
Summary
These techniques allow you to create a more intuitive and powerful admin interface, enhancing
the user experience for managing your Django models.
● Custom Methods: These are defined within the model to encapsulate logic related to
that model. They typically operate on individual model instances.
Example:
class Person(models.Model):
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=30)
age = models.IntegerField()
def age_status(self):
if self.age < 18:
return "under age"
return "adult"
Usage:
person = Person.objects.get(id=1)
print(person.age_status()) # Outputs: "adult" or "under age"
Computed Fields (Using @property): Properties allow for on-the-fly calculation of values
based on model fields. They do not save the result in the database but compute it when
accessed.
Example:
class Person(models.Model):
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=30)
@property
def full_name(self):
return f"{self.first_name} {self.last_name}"
Usage:
person = Person.objects.get(id=1)
print(person.full_name) # Outputs: "John Doe"
2. Overriding the save() Method: The save() method is executed when a model instance is
saved to the database. You can override it to add custom logic before or after saving.
Example:
class Post(models.Model):
title = models.CharField(max_length=255)
slug = models.SlugField()
Usage:
3. The Meta Class: The Meta class in a model allows you to define various metadata options
for your model, including table names, ordering, constraints, and more.
By default, Django creates a database table name by combining the app name and the model
name. You can override this default behavior by specifying a custom table name using
db_table.
Example:
class Product(models.Model):
name = models.CharField(max_length=255)
class Meta:
db_table = 'custom_product_table'
In this example, the Product model will use the table name custom_product_table instead
of the default appname_product.
You can specify the default ordering of querysets when retrieving objects from the database.
Example:
class Product(models.Model):
name = models.CharField(max_length=255)
In this example, products will be ordered by price in ascending order, and if two products have
the same price, they will be ordered by name.
verbose_name allows you to specify a human-readable name for the model, which is used in
the Django admin interface.
Example:
class Product(models.Model):
name = models.CharField(max_length=255)
class Meta:
verbose_name = 'Item'
unique_together ensures that a combination of fields must be unique across the entire table.
Example:
class Order(models.Model):
In this example, a customer cannot have the same product in their order list more than once.
You can create custom indexes on fields or expressions to optimize query performance.
Example:
class Product(models.Model):
name = models.CharField(max_length=255)
class Meta:
indexes = [
models.Index(fields=['price']),
models.Index(fields=['name', 'price']),
In this example, indexes are created on the price field and on the combination of name and
price fields to speed up lookups.
Example:
name = models.CharField(max_length=255)
class Meta:
constraints = [
models.CheckConstraint(check=Q(price__gte=0), name='price_positive'),
models.CheckConstraint(check=Q(discount_price__lte=F('price')),
name='valid_discount_price'),
In this example, the constraints ensure that the price is non-negative and that the
discount_price is not greater than the price.
You can define custom permissions that can be assigned to users or groups.
Example:
class Product(models.Model):
name = models.CharField(max_length=255)
class Meta:
permissions = [
An abstract model is a model that is not created in the database but can be inherited by other
models.
Example:
class TimestampedModel(models.Model):
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
class Meta:
abstract = True
class Product(TimestampedModel):
name = models.CharField(max_length=255)
class Order(TimestampedModel):
Django models can utilize Python's special magic methods to customize behaviors like
representation, initialization, comparison, and more.
Example:
class Author(models.Model):
name = models.CharField(max_length=100)
def __str__(self):
return self.name
Example:
class Author(models.Model):
name = models.CharField(max_length=100)
def __repr__(self):
Example:
class MyModel(models.Model):
name = models.CharField(max_length=100)
# Custom logic
super().save(*args, **kwargs)
Example:
class MyModel(models.Model):
name = models.CharField(max_length=100)
# Custom logic
super().delete(*args, **kwargs)
Example:
class MyModel(models.Model):
name = models.CharField(max_length=100)
3.1: FORMS
Step 1: Create the Model First, define the model for which you will fetch data. In this example,
we'll create an Employee model to store basic employee details.
# models.py
class Employee(models.Model):
name = models.CharField(max_length=90)
email = models.EmailField()
phone = models.IntegerField()
address = models.TextField()
Step 2: Create the Forms Django provides two ways to create forms: manually using
forms.Form or automatically using forms.ModelForm. Here’s how to create both types:
# forms.py
from django import forms
class YourForm(forms.Form):
name = forms.CharField(max_length=100)
email = forms.EmailField()
phone = forms.IntegerField()
class YourModelForm(forms.ModelForm):
class Meta:
model = Employee
fields = ['name', 'email', 'phone'] # Specify the fields to include in the form
Explanation:
Step 3: Write the Views Views are responsible for handling user input and rendering the
appropriate HTML template. Here, we create views to render our forms and handle form
submissions.
# views.py
form = YourForm()
def your_view_url_name(request):
if request.method == 'POST':
form = YourModelForm(request.POST)
if form.is_valid():
name = form.cleaned_data['name']
email = form.cleaned_data['email']
Explanation:
Step 4: Create the Templates The HTML template is where the form will be displayed. Below is
an example of how to create a template for displaying YourForm.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
</head>
<body>
<h1>Your Form</h1>
{% csrf_token %}
{{ form.non_field_errors }}
<div class="form-group">
{{ form.name }}
{{ form.name.errors }}
</div>
<div class="form-group">
{{ form.email }}
{{ form.email.errors }}
</div>
<div class="form-group">
{{ form.phone }}
{{ form.phone.errors }}
</div>
</form>
</body>
</html>
Explanation:
● The template uses Django template tags to render form fields and handle errors.
● The form’s action attribute points to the URL where the form will be submitted.
Step 5: Configure URLs Finally, set up the URL configurations for your views so that they can
be accessed via specific endpoints.
# project-level urls.py
urlpatterns = [
path("admin/", admin.site.urls),
path("app1/", include("app1.urls")),
# app-level urls.py
from django.urls import path
urlpatterns = [
Explanation:
Step 6: Display Data in a Template If you want to display the details of all employees stored in
the database, create a new view and template.
# views.py
def user_detail(request):
user_dict = Employee.objects.all()
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>User Details</title>
</head>
<body>
<ol>
{% endfor %}
</ol>
</body>
</html>
Explanation:
● user_detail: This view fetches all employee records and passes them to the
user_detail.html template.
● user_detail.html: The template iterates over the users context variable and displays
each user's name and email in an ordered list.
This completes the basic setup for handling forms in Django, displaying form data, and
rendering it in a template.
First, you need to define the models you will be working with. Here, we have three models:
Publisher, Author, and Book.
# models.py
class Publisher(models.Model):
name = models.CharField(max_length=30)
address = models.CharField(max_length=50)
city = models.CharField(max_length=60)
state_province = models.CharField(max_length=30)
country = models.CharField(max_length=50)
website = models.URLField()
class Meta:
ordering = ["-name"]
def __str__(self):
return self.name
class Author(models.Model):
salutation = models.CharField(max_length=10)
name = models.CharField(max_length=200)
email = models.EmailField()
headshot = models.ImageField(upload_to="author_headshots")
def __str__(self):
return self.name
class Book(models.Model):
title = models.CharField(max_length=100)
authors = models.ManyToManyField(Author)
publication_date = models.DateField()
Create a folder named templates in your project’s root directory, if it doesn’t already exist.
Inside the templates folder, create another folder with the same name as your app (e.g.,
app1). This is where you’ll place your HTML templates.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Publishers</title>
</head>
<body>
<h2>Publishers</h2>
<ul>
{% endfor %}
</ul>
</body>
</html>
Create a ListView for the Publisher model. This view will automatically detect the
publisher_list.html template you created earlier.
# views.py
class PublisherListView(ListView):
model = Publisher
This generic view will look for a template named publisher_list.html in the app1 directory
by default.
Step 4: Set Up URLs
Configure the URL patterns to connect your views with specific URLs
# app1/urls.py
urlpatterns = [
# project-level urls.py
urlpatterns = [
path("admin/", admin.site.urls),
path("app1/", include("app1.urls")),
When you need to present additional information, such as a list of books associated with each
publisher, you can extend the DetailView to include extra context data.
Create a DetailView for the Publisher model and override the get_context_data
method to add a list of books to the context.
# views.py
class PublisherDetailView(DetailView):
model = Publisher
context = super().get_context_data(**kwargs)
context["book_list"] = Book.objects.filter(publisher=self.object)
return context
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Publisher Detail</title>
</head>
<body>
<ul>
{% endfor %}
</ul>
</body>
</html>
Step 3: Update URLs
# app1/urls.py
urlpatterns = [
Conclusion
By following these steps, you have set up a Django project that auto-detects HTML templates
using generic views and extends the functionality of generic views to include additional context
data. This allows for a clean and efficient way to manage and display data within your Django
application.
First, create a static folder within your Django app. Inside the static folder, create a css
folder and place your CSS files inside it.
Directory Structure:
your_project/
├── your_app/
│ ├── static/
│ │ ├── css/
│ │ │ └── styles.css
│ │ ├── js/
│ │ └── images/
├── manage.py
└── your_project/
Step 2: Create the HTML File and Connect It to the CSS File
Create an HTML file in your templates directory that links to the CSS file using the {%
static %} template tag.
{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
</head>
<body>
<div class="main-content">
<h1>Hello, Django!</h1>
<hr>
</div>
</body>
</html>
/* static/css/styles.css */
body, h1, p {
margin: 0;
padding: 0;
background-color: #f4f4f4;
h1 {
color: #333;
background-color: #fff;
padding: 20px;
text-align: center;
.main-content {
max-width: 800px;
background-color: #fff;
padding: 20px;
/* Style links */
a{
color: #007bff;
text-decoration: none;
a:hover {
text-decoration: underline;
hr {
margin: 20px 0;
Example View:
# views.py
def css_view(request):
App-Level urls.py:
# urls.py
urlpatterns = [
Project-Level urls.py:
# project-level urls.py
urlpatterns = [
path("admin/", admin.site.urls),
When using Django's generic views, such as ListView, you often work with a subset of objects
from your database. While the model argument specifies which model to query, you can further
refine this using the queryset argument.
# views.py
class BookListView(ListView):
model = Book
Django's generic views are powerful tools that simplify the development of common web
patterns by providing reusable views that handle common tasks like displaying lists of objects,
showing detail views, handling forms, and more. Below are some of the most commonly used
generic views in Django.
1. ListView
model = YourModel
template_name = 'your_app/your_model_list.html'
class PersonDetails(ListView):
template_name = "person.html"
context_object_name = 'data'
def get_queryset(self):
data = Person.objects.all().first()
print(data.name)
return data
2. DetailView
class YourModelDetailView(DetailView):
model = YourModel
template_name = 'your_app/your_model_detail.html'
context_object_name = 'object' # Name of the variable to use in the template
3. CreateView
● Purpose: To display a form for creating a new object and handle form submissions.
class YourModelCreateView(CreateView):
model = YourModel
template_name = 'your_app/your_model_form.html'
4. UpdateView
class YourModelUpdateView(UpdateView):
model = YourModel
template_name = 'your_app/your_model_form.html'
class YourModelDeleteView(DeleteView):
model = YourModel
template_name = 'your_app/your_model_confirm_delete.html'
Django Rest Framework provides powerful tools for building REST APIs in Django. The
api_view decorator is central to this, allowing you to define which HTTP methods your view
should respond to.
def student_view(request):
if request.method == 'GET':
data = Student.objects.all().values()
if request.method == 'POST':
data = request.data
Student.objects.create(
name=data['name'],
student_id=data['student_id'],
grade_desc=data['grade_desc']
Throttle Example:
class OncePerDayUserThrottle(UserRateThrottle):
rate = '1/day'
@api_view(['GET'])
@throttle_classes([OncePerDayUserThrottle])
def view(request):
return Response({"message": "Hello for today! See you tomorrow!"})
Summary
These tools help streamline the development process and allow you to focus on the specific
business logic and customizations needed for your application.
In Django, handling data sent from an HTML form is straightforward. You can use Django's
HttpRequest object to access the data submitted through the form. Below is a step-by-step
guide to achieve this.
First, create an HTML form within your template, myform.html, located in the templates
directory.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>My Form</title>
</head>
<body>
<label for="username">Username:</label>
<br>
<label for="password">Password:</label>
<br>
</form>
</body>
</html>
Next, create the views in your views.py file to handle the form display and processing.
def my_form(request):
def process_form(request):
if request.method == 'POST':
# Get data from the form
username = request.POST.get('username')
password = request.POST.get('password')
else:
In your app's urls.py file, define the URL patterns to map the form view and the processing
view.
urlpatterns = [
]
Make sure these URLs are included in your main urls.py file if you're working within a larger
project.
Summary
● Form Handling: Django uses the HttpRequest object to access data sent from forms
using the POST method.
● CSRF Protection: The {% csrf_token %} template tag is crucial for protecting
against CSRF attacks.
● Form Processing: The process_form view checks the request method to ensure it's
processing a POST request, retrieves the data using request.POST.get(), and then
handles it as needed.
This basic example forms the foundation for handling more complex forms in Django. For more
advanced form processing, consider using Django's forms module, which provides built-in
validation, error handling, and more structured form management.
This detailed section on creating a superuser and overriding the AbstractUser model in
Django, as well as setting up a user API for CRUD operations, covers some advanced aspects
of Django user management. Here's a summary and enhancement of the steps provided:
Creating a Superuser:
1. Navigate to Project Directory: Open a terminal and navigate to your Django project's
root directory (where manage.py is located).
2. Run Command to Create Superuser: Execute the following command:
python manage.py createsuperuser
Enter Superuser Details: You'll be prompted to enter a username, email, and password. These
credentials will be used to access the Django admin panel.
Access Admin Panel: Start the development server with python manage.py runserver
and log in at http://localhost:8000/admin/ using the superuser credentials.
If you need more control over the user model, such as using an email instead of a username for
authentication or adding custom fields, follow these steps:
class CustomUserManager(BaseUserManager):
if not email:
email = self.normalize_email(email)
user.set_password(password)
user.save(using=self._db)
return user
def create_superuser(self, email, password=None, **extra_fields):
extra_fields.setdefault('is_staff', True)
extra_fields.setdefault('is_superuser', True)
class CustomUser(AbstractUser):
email = models.EmailField(unique=True)
username = None
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = []
objects = CustomUserManager()
def __str__(self):
return self.email
Update settings.py:
● Point Django to use your custom user model by setting AUTH_USER_MODEL in
settings.py:
AUTH_USER_MODEL = 'your_app.CustomUser'
● Run the following commands to create and apply the necessary database migrations:
To handle user creation through an API, you can use Django REST Framework (DRF):
class UserSerializer(ModelSerializer):
class Meta:
model = CustomUser
email=validated_data["email"],
password=validated_data["password"]
user.set_password(validated_data["password"])
user.save()
return user
● Handle HTTP requests (e.g., POST for creating users) and use the serializer for data
validation and saving:
@api_view(["POST"])
def user_create(request):
if request.method == "POST":
serializer = UserSerializer(data=request.data)
if serializer.is_valid():
user = serializer.save()
When a new user is created, we need to generate a token for that user. We can do this by using
Django signals.
@receiver(post_save, sender=CustomUser)
if created:
Token.objects.create(user=instance)
Explanation:
Serializers are used to convert complex data types like Django models into JSON and vice
versa.
class UserSerializer(ModelSerializer):
class Meta:
model = CustomUser
user = CustomUser(
email=validated_data['email'],
user.set_password(validated_data['password'])
user.save()
return user
Explanation:
● The UserSerializer includes email and password fields for the CustomUser
model.
● The create method ensures the password is hashed before saving the user.
@api_view(["POST"])
def user_create(request):
if request.method == "POST":
serializer = UserSerializer(data=request.data)
if serializer.is_valid():
user = serializer.save()
Explanation:
● This view allows clients to register a new user by sending a POST request with email
and password.
● Upon successful registration, the user's email is returned.
@csrf_exempt
@api_view(["POST"])
def login_view(request):
if request.method == 'POST':
data = request.data
login(request, user)
token = Token.objects.get(user=user)
else:
1. Explanation:
○ This view authenticates the user with their email and password.
○ If successful, it retrieves and returns the user’s token.
Step 4: Configure Django Settings
INSTALLED_APPS = [
'rest_framework',
'rest_framework.authtoken',
MIDDLEWARE = [
# Other middleware
'django.contrib.auth.middleware.AuthenticationMiddleware',
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework.authentication.TokenAuthentication',
],
1. Explanation:
○ This ensures that DRF uses token-based authentication for any incoming
requests.
Step 5: Create Protected Views
@api_view(["GET"])
@authentication_classes([TokenAuthentication])
@permission_classes([IsAuthenticated])
def authenticated_message(request):
Explanation:
● This view is protected by token authentication. Only authenticated users can access it.
class ProtectedView(APIView):
authentication_classes = [TokenAuthentication]
permission_classes = [IsAuthenticated]
def get(self, request):
Key: Authorization
Sometimes, you may need to manually handle tokens from the request headers.
@api_view(['GET'])
@permission_classes([IsAuthenticated])
def example_view(request):
auth_header = request.headers.get('Authorization')
What is an API?
An API (Application Programming Interface) allows applications to communicate with each
other. In Django, the most common use of the term "API" refers to building web APIs using
Django REST Framework (DRF). DRF is a powerful toolkit for building Web APIs that can
handle data serialization, authentication, permissions, and more.
To create a basic API using DRF, you typically define serializers, views, and URLs:
● Serializers handle the conversion of complex data types, such as Django models, into
JSON.
● Views define how the API responds to various HTTP methods (GET, POST, etc.).
● URLs determine the routes that map to specific views.
@api_view Decorator: The @api_view decorator allows you to define views that handle
specific HTTP methods (e.g., GET, POST).
Example:
1. Define a Model:
class Book(models.Model):
title = models.CharField(max_length=100)
author = models.CharField(max_length=100)
Create a Serializer:
class BookSerializer(serializers.ModelSerializer):
class Meta:
model = Book
fields = '__all__'
Define Views:
@api_view(['GET'])
def book_list(request):
books = Book.objects.all()
return Response(serializer.data)
@api_view(['GET'])
def book_detail(request, pk):
book = Book.objects.get(pk=pk)
serializer = BookSerializer(book)
return Response(serializer.data)
Configure URLs:
urlpatterns = [
urlpatterns = [
path('admin/', admin.site.urls),
path('api/', include('myapi.urls')),
]
Example:
Example:
@authentication_classes([BasicAuthentication, SessionAuthentication])
class MyAuthenticatedAPIView(APIView):
user = request.user
class DemoAPIView(APIView):
data = request.data
Product.objects.create(
name=data['name'],
price=data['price'],
desc=data['desc'],
rating=data['rating'],
offer=data['offer'],
org_email=data['org_email'],
org_website=data['org_website']
class ProductUpdate(APIView):
product_instance = Product.objects.get(id=id)
data = request.data
product_instance.org_website = data.get('org_website',
product_instance.org_website)
product_instance.save()
In this example, the Product model has multiple images stored in the ProductImage model.
Models:
class Product(models.Model):
price = models.IntegerField(null=True)
desc = models.TextField(null=True)
offer = models.BooleanField(default=False)
org_email = models.EmailField(null=True)
org_website = models.URLField(null=True)
class ProductImage(models.Model):
Serializer:
class ProductCreateSerializer(ModelSerializer):
prod_images = serializers.SerializerMethodField()
image_data = ProductImage.objects.filter(product_id=obj.id).values()
return image_data
class Meta:
model = Product
fields = "__all__"
prod_image = self.context.get("view").request.FILES
product_instance = Product.objects.create(**validated_data)
ProductImage.objects.create(product_id=product_instance, image=image)
return product_instance
image_datas = self.context.get("view").request.FILES
image_id = self.context["request"].data.get("prod_images_id")
delete_image_ids = []
if image_id:
delete_image_ids.append(int(delete_id))
instance.save()
ProductImage.objects.create(product_id=instance, image=image)
if delete_image_ids:
ProductImage.objects.filter(product_id=instance,
id__in=delete_image_ids).delete()
return instance
ViewSet:
class ProdCreateUpdate(ModelViewSet):
serializer_class = ProductCreateSerializer
queryset = Product.objects.all()
URLs:
router = DefaultRouter()
router.register("prodcreate", ProdCreateUpdate)
urlpatterns = [
path('crud/', include(router.urls)),
]
Adding Extra Paths to a ViewSet:
class ProductView(ModelViewSet):
queryset = Product.objects.all()
top_rated = Product.objects.filter(rating__gte=3).values()
Navigate to your project directory and create a new Django app named app1:
cd signup
Update Settings
In your project's settings.py, add the newly created app to the INSTALLED_APPS list and
configure the authentication backend:
# signup/settings.py
INSTALLED_APPS = [
'app1',
]
# Authentication
AUTHENTICATION_BACKENDS = [
'django.contrib.auth.backends.ModelBackend',
TEMPLATES = [
"BACKEND": "django.template.backends.django.DjangoTemplates",
"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",
],
},
},
]
Create Models
In your app's models.py, create a custom user model if you want to add additional fields
(optional):
# app1/models.py
class CustomUser(AbstractUser):
pass
# signup/settings.py
AUTH_USER_MODEL = 'app1.CustomUser'
Create forms for user registration and login in your app's forms.py:
# app1/forms.py
class SignUpForm(UserCreationForm):
class Meta:
model = CustomUser
class LoginForm(AuthenticationForm):
class Meta:
model = CustomUser
Create Views
Create views for user registration, login, and a home page in your app's views.py:
# app1/views.py
def signup(request):
if request.method == 'POST':
form = SignUpForm(request.POST)
if form.is_valid():
form.save()
username = form.cleaned_data.get('username')
raw_password = form.cleaned_data.get('password1')
login(request, user)
else:
form = SignUpForm()
def user_login(request):
if request.method == 'POST':
if form.is_valid():
user = form.get_user()
login(request, user)
else:
form = LoginForm()
def home_view(request):
Create templates for user registration, login, and the home page in your app's templates
folder:
signup.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Sign Up</title>
</head>
<body>
<h2>Sign Up</h2>
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Sign Up</button>
</form>
</body>
</html>
login.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Login</title>
</head>
<body>
<h2>Login</h2>
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Login</button>
</form>
</body>
</html>
home.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Home</title>
</head>
<body>
</body>
</html>
# app1/urls.py
urlpatterns = [
# signup/urls.py
urlpatterns = [
path('admin/', admin.site.urls),
path('app1/', include('app1.urls')),
Now you can access the signup and login pages at:
● Signup: http://localhost:8000/app1/signup/
● Login: http://localhost:8000/app1/login/
Once you log in, you will be redirected to the home page.
Additional Features
Here's a sample Django project structure that you can provide to your students. This project is
designed to include different apps for various machine learning algorithms, such as linear
regression and logistic regression. The project allows users to upload data files, select the type
of machine learning algorithm, and navigate accordingly.