Notes - Advanced Python Sem VI CBCS NEP 1.0
Notes - Advanced Python Sem VI CBCS NEP 1.0
Exception Handling: Exception, Exception Handling, except clause, Try, finally clause, User
Defined Exceptions.
Object Oriented Programming Concepts: Class and object, Attributes, Inheritance,
Overloading, Overriding, and Data hiding.
Introduction to Django: Concepts of Web Page, Django Project & server configuration, MVT
Design Pattern, View, Template, URL Mapping, Django Forms, Form Validation, Database
connectivity, Django Middleware, Session & cookies.
B.Sc. III Sem.VI (CBCS) (NEP 1.0) CS P-XVI ADVANCED PYTHON DSE-24F
The purpose of handling errors is to make the program robust that is strong. A robust
program does not terminate in the middle. Also, when there is an error in the program, it will
display an appropriate message to the user and continue exception. Designing such
programs is needed in any software development. For this purpose, the programmer should
handle the errors. When the errors can be handled, they are called exceptions. To handle
exceptions, the programmer should perform the following three steps:
Step 1: Observe the statements in his program where there may be a possibility if
exceptions. Such statements should be written inside a ‘try’ block. A try block looks like as
follows:
try:
statements
The greatness of try block is that even if some exception arises inside it, the program will not
be terminated. When PVM understands that there is an exception, it jumps into an ‘except’
block.
Step 2: The programmer should write the 'except' block where he should display the
exception details to the user. This helps the user to understand that there is some error in
the program. The programmer should also display a message regarding what can be done to
avoid this error. Except block looks like as follows:
except exceptionname:
statements #these statements form handler
The statements written inside an except block are called 'handlers' since they handle the
situation when the exception occurs.
Step 3: Lastly, the programmer should perform clean up actions like closing the files and
terminating any other processes which are running. The programmer should write this code
in the finally block. Finally block looks like as follows:
finally:
statements
The specialty of finally block is that the statements inside the finally block are executed
irrespective of whether there is an exception or not. This ensures that all the opened files are
properly closed and all the running processes are properly terminated. So, the data in the
files will not be corrupted and the user is at the safe-side.
Syntax:
try:
# Code block
# These statements are those which can probably have some error
except:
# This block is optional.
# If the try block encounters an exception, this block will handle it.
else:
# If there is no exception, this code block will be executed by the Python interpreter
finally:
# Python interpreter will always execute this code.
Example:
#a function to find total and average of list elements
def avg(list):
tot=0
for x in list:
tot+=x
avg=tot/len(list)
return tot,avg
try:
t,a=avg([1,2,3,4,5,’a’])
print(‘Total={}, Average={}’.format(t,a))
except TypeError:
print(‘Type Error, Please provide numbers’)
except ZeroDivisionError:
print(‘ZeroDivisionError, Please do not give empty list’)
But there may be some situations where none of the exceptions in Python are useful
for the programmer. In that case, the programmer has to create his own exception and raise
it. For this purpose, he has to follow these steps –
1. Since all exceptions are classes, the programmer is supposed to create his own exception
as a class. Also, he should make his class as a sub class of the in-built ‘Exception’ class.
class MyException(Exception):
def __init__(self,arg):
self.msg=arg
Here, ‘MyException’ class is the sub class of Exception class. this class has a constructor
where variable ‘msg’ is defined. Theis ‘msg’ receives a message passed from outside through
‘arg’.
2. The programmer can write his code; maybe it represents a group of statements or a
function. when the programmer suspects the possibility if exception, he should raise his
exception using ‘raise’ statement as :
raise MyException(“message”)
Here, raise statement is raising MyException class object that contains the given “message”.
3. The programmer can insert the code inside a try block and catch the exception using
except block as :
try:
code
except MyException as me:
prinit(me)
Here, the object ‘me’ contains the message given in the raise statement.
Example:
class MyException(Exception):
def __init__(self,arg):
self.msg=arg
amt=500
try:
if(amt<1000):
raise MyException(“Low account balance”)
except MyException as obj:
print(obj)
try:
check_positive(-5)
except ValueError as e:
print(e)
try:
divide(10, 0)
except ZeroDivisionError as e:
print(e)
def validate_age(age):
if age < 18:
raise InvalidAgeError("Age must be at least 18.")
print("Valid age.")
try:
validate_age(16)
except InvalidAgeError as e:
print(f"Error: {e}")
1.1.5 The assert Statement
The assert statement is useful to ensure that a given condition is True. If it is not true, it
raises AssertionError. The syntax is as follow:
assert condition,message
If the condition is False, then the exception by the name AssertionError is raised along with
the message written in the assert statement. If message is not given in the assert statement
and the condition is False, then also AssertionError is raised without message.
Example:
try:
x=int(input(“Enter a number between 5 and 10:”))
assert x<5 and x>10
print(“The entered number”,x)
except AssertionError as obj:
print(“Condition is not fullfilled”)
• Encapsulation. This principle states that all important information is contained inside
an object and only select information is exposed. The implementation and state of
each object are privately held inside a defined class. Other objects do not have access
to this class or the authority to make changes. They are only able to call a list of
public functions or methods. This characteristic of data hiding provides greater
program security and avoids unintended data corruption.
• Abstraction. Objects only reveal internal mechanisms that are relevant for the use of
other objects, hiding any unnecessary implementation code. The derived class can
have its functionality extended. This concept can help developers more easily make
additional changes or additions over time.
• Inheritance. Classes can reuse code from other classes. Relationships and subclasses
between objects can be assigned, enabling developers to reuse common logic while
still maintaining a unique hierarchy. This property of OOP forces a more thorough
data analysis, reduces development time and ensures a higher level of accuracy.
• Polymorphism. Objects are designed to share behaviors and they can take on more
than one form. The program will determine which meaning or usage is necessary for
each execution of that object from a parent class, reducing the need to duplicate
code. A child class is then created, which extends the functionality of the parent class.
Polymorphism allows different types of objects to pass through the same interface.
Everything in Python is an object, and almost everything has attributes and methods. All
functions have a built-in attribute __doc__, which returns the docstring defined in the
function source code. When we define a class, it needs to create an object to allocate the
memory. Consider the following example.
Example:
class car:
def __init__(self,modelname, year):
self.modelname = modelname
self.year = year
def display(self):
print(self.modelname,self.year)
c1 = car("Toyota", 2016)
c1.display()
In the above example, we have created the class named car, and it has two attributes
modelname and year. We have created a c1 object to access the class attribute. The c1
object will allocate memory for these values. We will learn more about class and object in
the next tutorial.
The method is a function that is associated with an object. In Python, a method is not
unique to class instances. Any object type can have methods.
obj = check()
print("Address of class object = ",id(obj))
1.2.1.2 Constructor
Constructors are generally used for instantiating an object. The task of constructors is
to initialize (assign values) to the data members of the class when an object of the class is
created. In Python the __init__() method is called the constructor and is always called when
an object is created. Syntax of constructor declaration :
def __init__(self):
# body of the constructor
Types of constructors:
1. default constructor: The default constructor is a simple constructor which
doesn’t accept any arguments. Its definition has only one argument which is a
reference to the instance being constructed.
Prof. N. S. Kulkarni (Cell: 9890966539/9096194081) 9
B.Sc. III Sem.VI (CBCS) (NEP 1.0) CS P-XVI ADVANCED PYTHON DSE-24F
Example constructor:
class Addition:
first = 0
second = 0
answer = 0
# parameterized constructor
def __init__(self, f, s):
self.first = f
self.second = s
def display(self):
print("First number = " + str(self.first))
print("Second number = " + str(self.second))
print("Addition of two numbers = " + str(self.answer))
def calculate(self):
self.answer = self.first + self.second
1.2.1.3 Destructor
Destructors are called when an object gets destroyed. In Python, destructors are not
needed as much as in C++ because Python has a garbage collector that handles memory
management automatically. The __del__() method is a known as a destructor method in
Python. It is called when all references to the object have been deleted i.e. when an object is
garbage collected.
def __del__(self):
# body of destructor
1.2.2 Attributes
As an object-oriented language, Python provides two scopes for attributes: class attributes
and instance attributes. Python class attributes are variables of a class that are shared
between all of its instances. They differ from instance attributes in that instance attributes
are owned by one specific instance of the class and are not shared between instances.
While the instance attribute in Python has exactly the same characteristics and definition as
other object-oriented languages, the class attribute is often mistakenly considered to be the
exact equivalent of the static attribute in Java or C++. Class attributes in Python and static
attributes in Java or C++ have a lot in common, but they have several behavioral differences
that I will highlight in this article.
• An instance attribute is a Python variable belonging to one, and only one, object. This
variable is only accessible in the scope of this object, and it’s defined inside the
constructor function, __init__(self,..) of the class.
• A class attribute is a Python variable that belongs to a class rather than a particular
object. It’s shared between all the objects of this class and is defined outside the
constructor function, __init__(self,...), of the class.
The below ExampleClass is a basic Python class with two attributes: class_attr and
instance_attr.
class ExampleClass(object):
class_attr = 0
The instance_attr is only accessible from the scope of an object. The class attribute
(class_attr) is accessible as both a property of the class and as a property of objects, as it’s
shared between all of them.
if __name__ == '__main__':
foo = ExampleClass(1)
bar = ExampleClass(2)
# print the instance attribute of the object foo
print (foo.istance_attr)
#print the instance attribute of the object var
print (bar.instance_attr)
#print the class attribute of the class ExampleClass as a property of the class itself
print (ExampleClass.class_attr)
#print the classattribute of the class as a proporty of the objects foo,bar
print (bar.class_attr)
print (foo.class_attr)
# try to print instance attribute as a class property
print (ExampleClass.instance_attr)
Notice that the class attribute can be accessed as a class property and as an instance
property, however, accessing an instance attribute as a class property raises an
AttributeError.
1.2.3 Inheritance
Inheritance is an important aspect of the object-oriented paradigm. Inheritance provides
code reusability to the program because we can use an existing class to create a new class
instead of creating it from scratch. In inheritance, the child class acquires the properties and
can access all the data members and functions defined in the parent class. A child class can
also provide its specific implementation to the functions of the parent class. In this section of
the tutorial, we will discuss inheritance in detail.
In python, a derived class can inherit base class by just mentioning the base in the bracket
after the derived class name. Consider the following syntax to inherit a base class into the
derived class.
Python Inheritance
Syntax
class derived-class(base class):
<class-suite>
A class can inherit multiple classes by mentioning all of them inside the bracket. Consider the
following syntax.
class derive-class(<base class 1>, <base class 2>, ..... <base class n>):
<class - suite>
Example
class Animal:
def speak(self):
print("Animal Speaking")
#child class Dog inherits the base class Animal
class Dog(Animal):
def bark(self):
print("dog barking")
d = Dog()
d.bark()
d.speak
class Animal:
def sound(self):
print("Animal makes a sound")
# Derived class
class Dog(Animal):
def bark(self):
print("Dog barks")
# Creating an object of the derived class
dog = Dog()
dog.sound() # Inherited method
dog.bark() # Method in the derived class
2. Multiple Inheritances
In multiple inheritance, a derived class inherits from more than one base class. This allows
the derived class to inherit features from multiple classes.
# Base classes
class Animal:
def sound(self):
print("Animal makes a sound")
class Dog:
def bark(self):
print("Dog barks")
# Derived class
class Hybrid(Dog, Animal):
def run(self):
print("Hybrid can run")
In this example:
• The class Hybrid inherits from both Dog and Animal, allowing it to access methods
from both base classes.
The Method Resolution Order (MRO):
When using multiple inheritance, Python follows the C3 Linearization (C3 superclass
linearization) algorithm to determine the order in which classes are checked for methods.
The mro() method can be used to view the MRO.
print(Hybrid.mro())
3. Multilevel Inheritance
In multilevel inheritance, a derived class becomes the base class for another derived class.
This creates a chain of inheritance where each class inherits from its predecessor.
# Base class
Prof. N. S. Kulkarni (Cell: 9890966539/9096194081) 13
B.Sc. III Sem.VI (CBCS) (NEP 1.0) CS P-XVI ADVANCED PYTHON DSE-24F
class Animal:
def sound(self):
print("Animal makes a sound")
# Intermediate class
class Mammal(Animal):
def has_hair(self):
print("Mammals have hair")
# Derived class
class Dog(Mammal):
def bark(self):
print("Dog barks")
4. Hierarchical Inheritance
In hierarchical inheritance, multiple derived classes inherit from a single base class. Each
derived class can have its own behavior while still sharing common functionality from the
base class.
# Base class
class Animal:
def sound(self):
print("Animal makes a sound")
# Derived class 1
class Dog(Animal):
def bark(self):
print("Dog barks")
# Derived class 2
class Cat(Animal):
def meow(self):
print("Cat meows")
cat = Cat()
cat.sound() # Inherited from Animal
cat.meow()
5. Hybrid Inheritance
Prof. N. S. Kulkarni (Cell: 9890966539/9096194081) 14
B.Sc. III Sem.VI (CBCS) (NEP 1.0) CS P-XVI ADVANCED PYTHON DSE-24F
# Base class 2
class Mammal:
def has_hair(self):
print("Mammals have hair")
# Derived class 1
class Dog(Animal, Mammal):
def bark(self):
print("Dog barks")
# Derived class 2
class Bat(Mammal, Animal):
def fly(self):
print("Bat can fly")
bat = Bat()
bat.has_hair() # Inherited from Mammal
bat.sound() # Inherited from Animal
bat.fly()
1.2.3.2 Super Function: The super() function is commonly used in inheritance to call
methods from a parent class. It ensures that the next method in the method resolution order
is called, which is particularly important in multiple and multilevel inheritance.
Example:
class Animal:
def speak(self):
print("Animal makes a sound")
class Dog(Animal):
def speak(self):
super().speak() # Calls Animal's speak method
print("Dog barks")
dog = Dog()
dog.speak() # Output: Animal makes a sound \n Dog barks
1.2.4 Overloading
Function overloading is the feature when multiple functions have the same name, but the
number of parameters in the functions varies. Python does not support function overloading
as in other languages, and the functional parameters do not have a data type. Suppose we
want to use the feature of functional overloading. In that case, we can set the default values
of parameters in the method as None, which won’t give an error if that specific value is not
passed as an argument while calling the function.
The problem with method overloading in Python is that we may overload the methods but
can only use the latest defined method.
def product(a, b):
p=a*b
print(p)
# Second product method Takes three argument and print their product
In the above code, we have defined two product methods we can only use the second
product method, as python does not support method overloading. We may define many
methods of the same name and different arguments, but we can only use the latest defined
method. Calling the other method will produce an error. Like here calling product(4,5) will
produce an error as the latest defined product method takes three arguments.
1.2.5 Overriding
When the parent class method is defined in the child class with some specific
implementation, then the concept is called method overriding. We may need to perform
method overriding in the scenario where the different definition of a parent class method is
needed in the child class.
Consider the following example to perform method overriding in python.
Example
class Animal:
def speak(self):
print("speaking")
class Dog(Animal):
def speak(self):
print("Barking")
d = Dog()
d.speak()
Prof. N. S. Kulkarni (Cell: 9890966539/9096194081) 16
B.Sc. III Sem.VI (CBCS) (NEP 1.0) CS P-XVI ADVANCED PYTHON DSE-24F
def sum(self):
self.__privateCounter += 1
print(self.__privateCounter)
count = Solution()
count.sum()
count.sum()
# Here we have accessed the private data member through class name.
print(count._Solution__privateCounter)
2. The linkage between the visible and invisible data makes the objects work faster, but
data hiding prevents this linkage.
Example:
class Employee:
def __init__(self, name, salary):
self.__name = name # Private attribute
self.__salary = salary # Private attribute
HTTP stands for Hypertext Transfer Protocol. This is the protocol being used to transfer
hypertext documents that makes the World Wide Web possible. A standard web address
such as Yahoo.com is called a URL and here the prefix http indicates its protocol
HTML stands for Hyper Text Markup Language. This is the language in which we write
web pages for any Website. Even the page you are reading right now is written in HTML.
This is a subset of Standard Generalized Mark-Up Language (SGML) for electronic
publishing, the specific standard used for the World Wide Web.
The browser sends the request for a page or a file via an HTTP request. The HTTP is
the Hypertext Transfer Protocol, a network protocol that allows transferring hypermedia
documents over the internet between a browser and server.
Once the request reaches the server, the HTTP server accepts the request, finds the
requested page, and sends it back to the browser through the HTTP response. If a server
is unable to find the requested page, it returns a 404 response.
July 2005 under the BSD license. Currently, DSF (Django Software Foundation) is
maintaining its development and release cycle.
Django is a web development framework for building websites and web applications
using Python. It provides a set of tools and features that make it easier to create web
applications quickly and efficiently. Django handles common web development tasks
like database management, URL routing, form handling, and user authentication,
allowing developers to focus on building the unique features of application instead of
reinventing the wheel. It follows the "Don't Repeat Yourself" (DRY) principle,
promoting code reuse and maintainability.
• Model
The Model represents the data and the business logic of the application. It defines
the structure of the database (or data source) and handles the interaction with
the data layer. This includes tasks like fetching, updating, and deleting data. In
Django, the Model is typically implemented using Django’s ORM (Object-
Relational Mapping), where each model is a Python class that maps to a database
Prof. N. S. Kulkarni (Cell: 9890966539/9096194081) 28
B.Sc. III Sem.VI (CBCS) (NEP 1.0) CS P-XVI ADVANCED PYTHON DSE-24F
table. The Model is also responsible for enforcing data validation rules and
providing an abstraction for accessing data from the underlying storage system.
Each Django model creates a corresponding database table, with each model
attribute becoming a field in the table.
• View
The View represents the user interface (UI) in the application. It is responsible for
rendering the data to the user and receiving input. However, unlike the MVC
pattern, where the View also handles user interaction, in MVT, the View is
focused solely on presenting the data.
In Django, the View refers to Python functions (or classes) that handle HTTP
requests and return HTTP responses. These views can render templates, pass data
to templates, and implement the business logic associated with handling user
requests. The View's role is to respond to user actions and invoke the necessary
logic in the Model to fetch data or perform some computation. It processes
incoming requests, retrieves data from the model, applies transformations, and
passes it to the template. Views in Django are Python functions or classes.
• Template
The Template is Django’s implementation of the View layer. It is responsible for
rendering the HTML that is returned to the client’s browser. It is a text file that
can include HTML and template tags (placeholders) that are replaced with
dynamic data when the page is generated. Templates allow the application to
present dynamic content by embedding data passed from the View layer into the
HTML. Django’s templating system provides a way to use control structures like
loops and conditional statements, making the presentation of data flexible. While
templates handle the presentation logic, they do not manage how the data is
obtained or how business rules are applied. Their primary role is to create the
final HTML to send to the browser.
Django templates are HTML files with placeholders for dynamic content, which
are filled in by the Django Template Language (DTL).
The MVT design pattern (Model-View-Template) is a variant of the MVC pattern that
structures web applications by separating the business logic (Model), user interface
(Template), and the request-handling logic (View). While the specific names and roles
of components differ from the traditional MVC pattern, the overall goal is the same:
to ensure clean separation of concerns, leading to maintainable, scalable, and
testable applications. MVT is particularly associated with Django, though the
pattern's concepts can be applied to other web development frameworks as well.
A client sends a request (such as loading a web page) to the server. The URL
dispatcher (which maps URLs to Views) processes the request and calls the
corresponding View function or class.
2. View Processing:
The View retrieves necessary data from the Model, processes it, and prepares the
context for the Template. In the case of dynamic content, the View may interact
with the database using Django’s ORM models, fetch data, and pass that data to
the Template.
3. Template Rendering:
The Template, which contains placeholders, receives the context data from the
View. The Template processes the data and returns a final HTML page to the
client, which is rendered in the user’s browser.
3. Testability:
o Since the application is broken into distinct layers (Model, View, Template),
testing becomes more straightforward. For example, you can unit-test the
Model and View layers independently.
4. Reusability:
o Templates allow for the reuse of presentation logic, reducing redundancy in
code. Likewise, Models can be reused across different Views.
• Template
A Template is a web page in which HTML script is interspersed with the code blocks of
Django Template Language.
Django’s template processor uses any context data received from the View is inserted
in these blocks so that a dynamic response is formulated. The View in turn returns
the response to the user.
2.5 View
In Django, a view is a Python function or class that takes an HTTP request and returns
an HTTP response. Views can render HTML templates, redirect to other pages, return
data in various formats (such as JSON), or even trigger complex logic. Views handle
the user interaction with your website by processing user requests and returning
appropriate responses.
In Django, the View is a crucial component of the MVT (Model-View-Template) design
pattern, responsible for handling HTTP requests, interacting with models, processing
the necessary data, and returning an HTTP response. Unlike the Model, this defines
the data and business logic, and the Template, which handles presentation, the View
o request: The HTTP request object that contains metadata about the incoming
request (headers, user info, etc.).
o HttpResponse: A class that returns an HTTP response. You can also use
render() to return HTML pages rendered with templates.
• Advantages of FBVs:
o Simple and easy to understand.
o Explicit flow of control, making them a good choice for smaller applications or
simple views.
o Offers complete control over the request-response cycle.
• Limitations of FBVs:
o Can become repetitive and cumbersome for complex applications with many
views.
o Lack the built-in reusable behavior found in class-based views.
2. Map the view to a URL: Django uses a URL dispatcher to map URLs to view
functions. To associate the home view with a URL, you need to configure it in
the urls.py file of your app. If you don’t already have a urls.py in your app,
create one in the myapp directory. Inside myapp/urls.py, define the URL
pattern for the view:
from django.urls import path
from . import views
urlpatterns = [
path('', views.home, name='home'),
]
• path('', views.home) means that when a user accesses the root URL (/), the
home view will be called.
• name='home' is an optional name you can give to the URL, useful for reverse
URL resolution in templates.
3. Include the app URLs in the main urls.py: In the main urls.py of the project
(usually found in the myproject directory), include the URLs from myapp.
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('myapp.urls')), # Include the URLs of 'myapp'
]
4. Run the server: Now, when you visit http://127.0.0.1:8000/, you should see
the text "Hello, world!" in your browser.
• Advantages of CBVs:
o Promotes reuse of common behavior using mixins and base classes.
o Easier to extend and maintain for complex views, as you can break logic into
multiple methods (e.g., get, post, put).
o Django provides built-in generic class-based views like ListView, DetailView,
CreateView, UpdateView, and DeleteView that automatically handle common
tasks like displaying a list of objects or managing forms.
• Limitations of CBVs:
o More abstract and can be harder to understand for beginners.
o Requires understanding of object-oriented programming (OOP) concepts like
inheritance and mixins.
2. Map the class-based view to a URL: To associate the class-based view with a
URL, you need to use as_view() when defining the URL pattern. This is
necessary to instantiate the class and returns a callable view.
In myapp/urls.py:
from django.urls import path
from .views import HomeView
urlpatterns = [
path('', HomeView.as_view(), name='home'),
]
o HomeView.as_view() creates an instance of HomeView and returns it as a
callable view that can be used by the URL dispatcher.
3. Run the server: Now, when you visit http://127.0.0.1:8000/, you will see the
message "Hello, world from a class-based view!" in your browser.
urlpatterns = [
path('hello/', views.my_view, name='hello'),
]
In this case, when a user visits /hello/, the my_view function will handle the request.
2. View Processing:
The view takes the incoming HTTP request, processes it, and typically interacts with
the Model to fetch or modify data. The view may also involve validating user input,
applying business logic, or performing additional tasks.
3. Template Rendering (Optional):
If the view needs to return HTML, it will typically render a Template (which is an
HTML file with dynamic placeholders) using the render() function.
Example:
from django.shortcuts import render
def my_view(request):
context = {'message': 'Hello, World!'}
return render(request, 'my_template.html', context)
4. Returning the Response:
The view then generates and returns an appropriate HTTP response. If it's a simple
page, the view will return an HttpResponse with rendered HTML. For API responses,
it might return JsonResponse.
2.6 Template
Django provides a convenient way to generate dynamic HTML pages by using its
template system. A template consists of static parts of the desired HTML output as
well as some special syntax describing how dynamic content will be inserted. In HTML
file, we can't write python code because the code is only interpreted by python
interpreter not the browser. We know that HTML is a static markup language, while
Python is a dynamic programming language. Django template engine is used to
separate the design from the python code and allows us to build dynamic web pages.
In Django, a template is a file that defines the structure and layout of the HTML
content that will be rendered by the server and sent to the browser. Templates are
used to separate the logic of your application (in views) from its presentation (the
HTML output).
Django uses a powerful templating engine that allows you to embed dynamic data
(like variables, loops, and conditionals) within your HTML files. These templates are
typically stored in the templates directory of your application or project.
A Template in Django is an HTML file (with optional Django template language
embedded) that defines how the data should be presented. Templates are
responsible for rendering data into HTML, which is then sent as an HTTP response to
the client (browser). Django templates use a specialized template language that
allows for the dynamic insertion of variables and the use of logic like loops,
conditionals, and more.
2.6.1 Template Files:
Templates are typically written as .html files, but they can be named with other
extensions if needed (e.g., .txt, .xml). These files contain HTML markup with Django
Template Language (DTL) embedded within the HTML structure. A template will
generally consist of static HTML mixed with dynamic placeholders that are replaced
with actual data when the template is rendered. Example of a simple Django
template (home.html):
<html>
<body>
<h1>Welcome, {{ user.name }}!</h1>
<p>We have {{ product_count }} products in our store.</p>
</body>
</html>
In this example, {{ user.name }} and {{ product_count }} are placeholders that will be
replaced with actual values when the template is rendered.
<main>
{% block content %}
{% endblock %}
</main>
</body>
</html>
Example of a child template (home.html):
{% extends 'base.html' %}
{% block content %}
<h2>Welcome to the homepage!</h2>
<p>Some dynamic content here...</p>
{% endblock %}
In this setup, the child template (home.html) inherits the structure defined in the
base template (base.html), and only the content inside the {% block content %} will
be replaced.
static, and media files are stored in a directory defined in the settings (e.g., media).
The {% static %} template tag is used to link to static files in templates.
Example:
<link rel="stylesheet" href="{% static 'css/styles.css' %}">
<img src="{% static 'images/logo.png' %}" alt="Logo">
In Django, a Template is a powerful tool for rendering dynamic content in the web
application. It is responsible for presenting data to the user in a structured and secure
manner. Django’s template system offers a range of features, such as template inheritance,
filtering, and tagging, which make it easy to manage and extend the presentation layer of
your application. By separating business logic and presentation logic, Django templates
improve maintainability, reusability, and security in web development.
1. Request URL: The user requests a specific URL in their browser (e.g.,
http://www.example.com/blog/).
2. Django URL Resolver: Django's URL resolver examines the incoming URL and tries to
find a matching pattern in the URL configuration.
3. Matching URL Pattern: If a URL pattern is found that matches the request URL, the
corresponding view is invoked to handle the request.
4. Response: The view generates a response (e.g., an HTML page, JSON data, etc.),
which is then sent back to the user's browser.
Explanation:
path(): The function path() is used to define URL patterns. It takes at least two
arguments:
o The first argument is the URL string (relative to the root of the site) that is
matched with the request URL.
o The second argument is the view that will be executed when the URL is
matched.
o Optionally, the third argument is a name for the URL pattern, which is
helpful for reverse URL lookup.
2. URL Pattern Matching
Django URL patterns use regular expressions (or simpler path converters in modern
versions) to match URL patterns. There are two main ways to define URL patterns in
Django:
a. Static URL Patterns (Fixed URLs)
These patterns match exactly with the requested URL.
Example:
urlpatterns = [
path('about/', views.about_view, name='about'), # Static URL pattern
]
Here, any request to http://www.example.com/about/ will be mapped to the
about_view function.
3. Path Converters
Django's modern URL handling system supports path converters, which are simpler
alternatives to regular expressions for capturing dynamic parts of a URL.
The available path converters are:
• <int:variable_name>: Matches an integer and passes it as a Python integer to the
view.
• <str:variable_name>: Matches a string and passes it as a string.
# blog/views.py
from django.shortcuts import render
from .models import BlogPost
def blog_list(request):
posts = BlogPost.objects.all()
<!--blog_list.html-->
<h1>Blog Posts</h1>
<ul>
{% for post in posts %}
<li><a href="{% url 'blog_post' post.id %}">{{ post.title }}</a></li>
{% endfor %}
</ul>
Note that all types of work done by forms in Django can be done with advanced
HTML stuff, but Django makes it easier and efficient especially the validation part.
Once you get hold of forms in Django you will just forget about HTML forms.
Django forms are Python classes that represent HTML forms. They simplify the
creation and processing of forms by providing built-in features for rendering HTML,
validating data, and interacting with models.
2.8.3 Widgets
Widgets determine the HTML representation of form fields. Django provides default widgets
for fields but allows customization.
Example:
message = forms.CharField(widget=forms.Textarea(attrs={'rows': 5, 'cols': 30}))
2.8.4 Validation
Django validates form data through:
• Field-specific Validation: Built into each field (e.g., EmailField checks for valid email
format).
• Custom Validation Methods: Defined using the clean_<fieldname>() method.
Prof. N. S. Kulkarni (Cell: 9890966539/9096194081) 45
B.Sc. III Sem.VI (CBCS) (NEP 1.0) CS P-XVI ADVANCED PYTHON DSE-24F
2.8.8 Example
1. forms.py:
python
CopyEdit
class ContactForm(forms.Form):
name = forms.CharField(max_length=100)
email = forms.EmailField()
message = forms.CharField(widget=forms.Textarea)
2. views.py:
python
CopyEdit
from django.shortcuts import render
from .forms import ContactForm
def contact_view(request):
if request.method == 'POST':
form = ContactForm(request.POST)
if form.is_valid():
# Process the form data
print(form.cleaned_data)
else:
form = ContactForm()
return render(request, 'contact.html', {'form': form})
3. contact.html:
html
CopyEdit
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Submit</button>
</form>
development, as it ensures data integrity, prevents malicious input, and enhances the
user experience by guiding users to provide correct information.
Form validation verifies that:
• All required fields are filled.
• Input data matches the expected type (e.g., integers, emails).
• Data adheres to specific rules (e.g., a password's minimum length).
• Custom conditions or relationships between fields are satisfied.
In web development frameworks like Django, form validation is handled through
built-in methods and can be extended with custom validation logic.
b) Server-Side Validation
Performed on the server after the form is submitted.
• Pros:
o Ensures secure and reliable validation.
o Handles all data submitted, even if client-side validation is bypassed.
• Cons:
o Slightly slower as it requires a server round-trip.
Example in Django:
from django import forms
class RegistrationForm(forms.Form):
username = forms.CharField(max_length=100)
email = forms.EmailField()
password = forms.CharField(widget=forms.PasswordInput)
def clean_email(self):
email = self.cleaned_data.get('email')
if not email.endswith('@example.com'):
Example:
name = forms.CharField(max_length=50, required=True)
if password != confirm_password:
raise forms.ValidationError("Passwords do not match.")
def clean_username(self):
username = self.cleaned_data.get('username')
if not username.isalnum():
raise forms.ValidationError("Username must be alphanumeric.")
return username
Example 2: Registration Form with Password Validation
class RegistrationForm(forms.Form):
username = forms.CharField(max_length=50)
email = forms.EmailField()
password = forms.CharField(widget=forms.PasswordInput)
confirm_password = forms.CharField(widget=forms.PasswordInput)
def clean(self):
cleaned_data = super().clean()
password = cleaned_data.get('password')
confirm_password = cleaned_data.get('confirm_password')
if password != confirm_password:
raise forms.ValidationError("Passwords must match.")
'ENGINE': 'django.db.backends.sqlite3',
'NAME': BASE_DIR / 'db.sqlite3',
}
}
def __str__(self):
return self.title
b. Migrating Models
Once models are defined, Django requires you to create and apply database migrations
to synchronize the models with the database schema.
1. Create Migrations:
python manage.py makemigrations
2. Apply Migrations:
python manage.py migrate
Django application and the server, allowing developers to process data during the
request-response lifecycle.
Middleware is a lightweight, pluggable layer of logic that is executed during the
processing of HTTP requests and responses. It allows for various functionalities such
as request preprocessing, response postprocessing, and exception handling.
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
a. SecurityMiddleware
Provides security enhancements like HTTP Strict Transport Security (HSTS).
b. SessionMiddleware
Manages session data across requests.
c. CommonMiddleware
Handles common tasks such as appending slashes to URLs or managing URL
redirects.
d. CsrfViewMiddleware
Adds Cross-Site Request Forgery (CSRF) protection to requests.
e. AuthenticationMiddleware
Associates users with requests, enabling user authentication.
f. MessageMiddleware
Handles messages sent to users during the request-response cycle.
g. XFrameOptionsMiddleware
Prevents the site from being embedded in an iframe to protect against
clickjacking.
• Registering Middleware
Custom middleware must be added to the MIDDLEWARE setting in
settings.py.
Example:
MIDDLEWARE = [
'myapp.middleware.CustomHeaderMiddleware',
'django.middleware.security.SecurityMiddleware',
# Other middleware...
]
2.12 Session
All communication between web browsers and servers is via HTTP, which is stateless.
The fact that the protocol is stateless means that messages between the client and
server are completely independent of each other — there is no notion of "sequence"
or behavior based on previous messages. As a result, if you want to have a site that
keeps track of the ongoing relationships with a client, you need to implement that
yourself.
Sessions are the mechanism used by Django (and most of the Internet) for keeping
track of the "state" between the site and a particular browser. Sessions allow you to
store arbitrary data per browser, and have this data available to the site whenever
the browser connects. Individual data items associated with the session are then
referenced by a "key", which is used both to store and retrieve the data.
Django uses a cookie containing a special session id to identify each browser and its
associated session with the site. The actual session data is stored in the site database
by default (this is more secure than storing the data in a cookie, where they are more
vulnerable to malicious users). You can configure Django to store the session data in
other places (cache, files, "secure" cookies), but the default location is a good and
relatively secure option.
2.12.1 Enabling sessions
Sessions were enabled automatically when we created the skeleton website. The
configuration is set up in the INSTALLED_APPS and MIDDLEWARE sections of the
project file (settings.py), as shown below:
INSTALLED_APPS = [
#…
'django.contrib.sessions',
#…
MIDDLEWARE = [
#…
'django.contrib.sessions.middleware.SessionMiddleware',
# …]
If you're updating some information within session data, then Django will not
recognize that you've made a change to the session and save the data (for example, if
you were to change wheels data inside your my_car data, as shown below). In this
case you will need to explicitly mark the session as having been modified.
# Session object not directly modified, only data within the session. Session
changes not saved!
request.session['my_car']['wheels'] = 'alloy'
# Set session as modified to force data updates/cookie to be saved.
request.session.modified = True
Add the line shown at the bottom of the following block to your main HTML template
(/django-locallibrary-tutorial/catalog/templates/index.html) at the bottom of the
"Dynamic content" section to display the num_visits context variable.
<h2>Dynamic content</h2>
<p>The library has the following record counts:</p>
<ul>
<li><strong>Books:</strong> {{ num_books }}</li>
<li><strong>Copies:</strong> {{ num_instances }}</li>
<li><strong>Copies available:</strong> {{ num_instances_available }}</li>
<li><strong>Authors:</strong> {{ num_authors }}</li>
</ul>
<p>
You have visited this page {{ num_visits }} time{{ num_visits|pluralize }}.
</p>
Note that we use the Django built-in template tag pluralize to add an "s" when the
page has been visited multiple times. Save your changes and restart the test server.
Every time you refresh the page; the number should update.
2.13 Cookies
Cookies, technically called HTTP Cookies are small text files which are created and
maintained by your browser on the particular request of Web-Server. They are stored
locally by your browser, and most browser will also show you the cookies generated
in the Privacy and Security settings of the browser. HTTP is a stateless protocol. When
any request is sent to the server, over this protocol, the server cannot distinguish
whether the user is new or has visited the site previously. Suppose, you are logging in
any website, that website will respond the browser with some cookies which will
have some unique identification of user generated by the server and some more
details according to the context of the website. Cookies made these implementations
possible with ease which were previously not possible over HTTP implementation.
return response
b. Getting Cookies:
def get_cookie_view(request):
value = request.COOKIES.get('key', 'default_value')
return HttpResponse(f"The value of the cookie is: {value}")
c. Deleting Cookies:
def delete_cookie_view(request):
response = HttpResponse("Cookie Deleted!")
response.delete_cookie('key')
return response