Module 3 - FSD
Module 3 - FSD
• Topics:
1. Activating Admin Interfaces
2. Using Admin Interfaces
3. Customizing Admin Interfaces
4. Reasons to Use Admin Interfaces
5. Form Processing, Creating feedback forms
6. Form Submission, Custom Validation, Creating model forms
7. UrlConf Ticks, Including other URLConfs
Introduction
• For a certain class of Web sites, an admin interface is an essential part of the
infrastructure. This is a Web-based interface, limited to trusted site
administrators, that enables the adding, editing, and deletion of site content.
• This chapter is about Django’s automatic admin interface. The feature works by
reading metadata in your model to provide a powerful and production-ready
interface that site administrators can start using immediately.
The django.contrib Packages
• django.contrib is a package that contains a collection of Django’s built-in
applications and utilities, which are often referred to as "contrib" apps.
• These apps provide commonly needed features and functionalities that you can
easily integrate into your Django projects. One of the most notable contrib apps is
the Django admin interface.
• The django.contrib package includes several modules, but the most relevant one
for the admin interface is django.contrib.admin
Activating the Admin Interface
The Django admin site is entirely optional, because only certain types of sites need this
functionality. That means you’ll need to take a few steps to activate it in your project.
First, make a few changes to your settings file:
1. Add 'django.contrib.admin' to the INSTALLED_APPS setting. (The order of INSTALLED_
APPS doesn’t matter, but we like to keep things alphabetical so it’s easy for a human to
read.)
2. Make sure INSTALLED_APPS contains 'django.contrib.auth','django.contrib.
contenttypes', and 'django.contrib.sessions'. The Django admin site requires these three
packages.
3. Make sure MIDDLEWARE_CLASSES contains 'django.middleware.common.
CommonMiddleware’, 'django.contrib.sessions.middleware.SessionMiddleware', and
'django.contrib. auth.middleware.AuthenticationMiddleware’.
Activating the Admin Interface
Second, run python manage.py syncdb. This step will install the extra database tables that
the admin interface uses.
Now in recent versions of Django, This command has been removed . We have to use
python manage.py makemigrations and python manage.py migrate commands instead.
Third, add the admin site to your URLconf (in urls.py, remember). By default, the urls.py
generated by django-admin.py startproject contains commented-out code for the Django
admin, and all you have to do is uncomment it.
But in the recent versions of Django, these lines are already uncommented.
Next, Create username and password to login to the admin site of Django using python
manage.py createsuperuser command
Activating the Admin Interface
• Now we can see the Django admin site in action. Just run the development server
(python manage.py runserver) and visit http://127.0.0.1:8000/admin/ in your
Web browser. The admin page will be displayed.
• In this case, NULL is the only way to specify an empty value. In Django models,
you can specify that NULL is allowed by adding null=True to a field.
• In short, if you want to allow blank values in a date field (e.g., DateField,
TimeField, DateTimeField) or numeric field (e.g., IntegerField, DecimalField,
FloatField), you’ll need to use both null=True and blank=True.
Making Date and Numeric Fields
Optional
class Publisher(models.Model):
name = models.CharField(max_length=100)
Customizing the admin Interfaces
Customizing Field lables
• In the Django admin site, each field’s label is derived from its model field name.
• To customize a label, use the verbose_name attribute in your model field definitions.
The verbose_name attribute is used in recent versions of Django. It allows you to set a
human-readable name for the field, which can be particularly useful for labels in forms and
in the admin interface. So, you can definitely keep using it in your models
Example: To change the Author.email field's label to “e-mail”:
class Author(models.Model):
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=40)
email = models.EmailField(blank=True, verbose_name='e-mail’)
class Author(models.Model):
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=40)
email = models.EmailField('e-mail', blank=True)
Customizing the admin Interfaces
Example:
class BookAdmin(admin.ModelAdmin):
fields = ('title', 'authors', 'publisher', 'publication_date')
Customizing the admin Interfaces
• Excluding Fields
• Exclude fields by omitting them from the fields list:
In admin.py file below code to be added.
Example:
class BookAdmin(admin.ModelAdmin):
fields = ('title', 'authors', 'publisher')
Customizing the admin Interfaces
After applying all the options for admin page such as list display, list filter, date
hierarchy, ordering and search fields, you can see the admin page something like this
which is shown below:
Example:
class BookAdmin(admin.ModelAdmin):
filter_horizontal = ('authors’,)
class BookAdmin(admin.ModelAdmin):
filter_vertical = ('authors',)
Customizing the admin Interfaces
• ForeignKey Field Widgets
• Use raw_id_fields for ForeignKey fields:
Example:
class BookAdmin(admin.ModelAdmin):
raw_id_fields = ('publisher',)
Customizing the admin Interfaces
• Another example for manytomany fields which can be executed in Django.
In models.py file:
from django.db import models
class Writer(models.Model):
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=40)
email = models.EmailField('e-mail', blank=True)
def __str__(self):
return f"{self.first_name} {self.last_name}"
Customizing the admin Interfaces
Continued….
class Publication(models.Model):
title = models.CharField(max_length=30)
publisher = models.CharField(max_length=40)
published_date = models.DateField()
writers = models.ManyToManyField(Writer)
def __str__(self):
return self.title
Customizing the admin Interfaces
In admin.py file:
• Reusability: Forms defined in forms.py can be reused across multiple views or templates.
For instance, if you need the same form in different parts of your application, you don’t
have to rewrite the form logic repeatedly.
Form Processing - Introduction
• Built-in Validations: Django's forms provide powerful built-in validations and error
handling, which can be implemented in forms.py. This avoids duplicating validation logic in
multiple places.
• Simplifies Template Code: Moving the form logic out of templates and into forms.py keeps
the HTML cleaner and focused on rendering. This is especially helpful when working on
complex forms.
• So, while embedding forms directly in templates might work for simpler use cases,
Django’s structured approach with forms.py is designed to scale with your application's
complexity. It’s all about maintainability and reducing redundant code!
Form Processing
1. Introduction to Forms
• Django provides a built-in form handling functionality that simplifies the process of
handling HTML forms in web applications.
• Forms in Django are represented by Python classes that map to HTML form fields.
2. Creating a Form
• In Django, forms are created by subclassing the forms.Form class or the forms.ModelForm
class (for model-based forms).
• Each form field is represented by a class attribute, and the type of the field is determined
by the corresponding Django Field class.
Form Processing
• Example:
7. Form Widgets
• Django provides a wide range of built-in form widgets (e.g., TextInput, Textarea,
CheckboxInput, Select, etc.) for rendering form fields.
• You can customize the rendering of form fields by specifying the widget argument
when defining the field.
Form Processing
8. Form Handling in Views
• In the view function, you typically create a form instance, bind the data to it, and
perform validation and data handling.
• After successful form submission, you can redirect the user to another page or render
a success message.
9. CSRF Protection
• Django provides built-in protection against Cross-Site Request Forgery (CSRF) attacks
by including a CSRF token in forms.
• You need to include the {% csrf_token %} template tag in your form template to
generate the CSRF token.
Form Processing
10. Form Inheritance
• Django supports form inheritance, allowing you to create reusable form
components and extend or override them as needed.
• You can use the Meta class to specify form-level attributes, such as labels,
help_texts, and error_messages.
Your First Form class – Creating
Feedback forms
Step 1: Create the Feedback Form Create a new file forms.py in your Django app directory,
and add the following code
<!DOCTYPE html>
<html>
<head>
<title>Feedback Form</title>
</head>
<body>
<h1>Feedback Form</h1>
<form method="post">
{% csrf_token %}
{{ form.non_field_errors }}
<div>
{{ form.name.errors }}
{{ form.name.label_tag }}
{{ form.name }}
</div>
Tying form objects into Views
FeedbackForm.html continued……
<div>
{{ form.email.errors }} {{ form.message.label_tag }}
{{ form.email.label_tag }} {{ form.message }}
{{ form.email }} </div>
</div> <input type="submit" value="Submit Feedback">
<div> </form>
{{ form.subject.errors }} </body>
{{ form.subject.label_tag }} </html>
{{ form.subject }}
</div>
<div>
{{ form.message.errors }}
Tying form objects into Views
Creating a success template named as : success.html
<!DOCTYPE html>
<html>
<head>
<title>Feedback Submitted</title>
</head>
<body>
<h1>Thank you for your feedback!</h1>
<p>We appreciate your comments, and will review them shortly.</p>
</body>
</html>
Changing How Fields Are Rendered
Probably the first thing you’ll notice when you render this form locally is that the message
field is displayed as an , and it ought to be a <textarea>. We can fix that by setting the field’s
widget:
from django import forms
class FeedbackForm(forms.Form):
name = forms.CharField(max_length=100, label='Your Name')
email = forms.EmailField(label='Your Email')
subject = forms.CharField(max_length=200, label='Subject')
message = forms.CharField(widget=forms.Textarea, label='Your Feedback')
The forms framework separates out the presentation logic for each field into a set of widgets.
Each field type has a default widget, but you can easily override the default or provide a
custom widget of your own. Think of the Field classes as representing validation logic, while
widgets represent presentation logic.
Setting a Maximum Length
• One of the most common validation needs is to check that a field is of a certain size. For
good measure, we should improve our ContactForm to limit the subject to 100 characters. To
do that, just supply a max_length to the CharField, like this:
<div class="field">
{{ form.message.errors }}
<label for="id_message">Message:</label>
{{ form.message }}
</div>
<input type="submit" value="Submit">
</form>
</body>
</html>
Customizing Form Design
3. Advanced Error Handling in Template:
{{ form.message.errors }} displays a <ul class="errorlist"> if errors are present and a blank string if the field is
valid (or the form is unbound). We can also treat form.message.errors as a Boolean or even iterate over it as a
list.
Consider this example:
<div class="field{% if form.message.errors %} errors{% endif %}">
{% if form.message.errors %}
<ul>
{% for error in form.message.errors %} This template:
• Checks for errors and displays them if present.
<li><strong>{{ error }}</strong></li> • Lists individual error messages in an unordered list.
{% endfor %}
</ul>
{% endif %}
<label for="id_message">Message:</label>
{{ form.message }}
Creating Model Forms
The following steps are required for creating model forms:
1. Define the Model: Establish your data structure with a Django model.
2. Create the Model Form: Generate a form using forms.ModelForm based on the model.
3. Add Custom Validation: Optionally include custom validation methods within the form.
4. Use the Form in Views: Implement form handling logic in Django views to process
submissions.
5. Create the Template: Design an HTML template to display and manage the form
interface.
Example code for creating model
forms:
1. Define the Model in models.py
• Objective: Create a Django model to represent the data structure.
Example:
from django.db import models
class Contact(models.Model):
subject = models.CharField(max_length=100)
email = models.EmailField(blank=True)
message = models.TextField()
def __str__(self):
return self.subject
Example code for creating model
forms:
2. Create the Model Form in forms.py file
Objective: Use forms.ModelForm to create a form based on the model.
Example
from django import forms
from .models import Contact
class ContactForm(forms.ModelForm):
class Meta:
model = Contact
fields = ['subject', 'email', 'message']
Example code for creating model
forms:
3. Add Custom Validation (Optional) in models.py
Add custom validation logic specific to form fields.
Example:
class ContactForm(forms.ModelForm):
class Meta:
model = Contact
fields = ['subject', 'email', 'message’]
def clean_message(self):
message = self.cleaned_data['message’]
num_words = len(message.split())
if num_words < 4:
raise forms.ValidationError("Not enough words!")
return message
Example code for creating model
forms:
4. Use the Form in Views Example
Objective: Handle the form submission and validation within Django views.
Example:
from django.shortcuts import render, redirect
from .forms import ContactForm
def contact_view(request):
if request.method == 'POST’:
form = ContactForm(request.POST)
if form.is_valid():
form.save()
return redirect('success') # Redirect to a success page or another view
else:
form = ContactForm()
return render(request, 'contact_form.html', {'form': form})
Example code for creating model
forms:
Create the Template
Objective: Design an HTML template to render and display the form.
<!DOCTYPE html>
<html>
<head>
<title>Contact Us</title>
</head>
<body>
<h1>Contact Us</h1>
{% if form.errors %}
<p style="color: red;">
Please correct the error{{ form.errors|pluralize }} below.
</p>
{% endif %}
Example code for creating model
forms:
Create the Template continued…
Objective: Design an HTML template to render and display the form.
<form method="post">
{% csrf_token %}
<div class="field">
{{ form.subject.errors }}
<label for="id_subject">Subject:</label>
{{ form.subject }}
</div>
<div class="field">
{{ form.email.errors }}
<label for="id_email">Your email address:</label>
{{ form.email }}
</div>
Example code for creating model
forms:
Create the Template continued…
Objective: Design an HTML template to render and display the form.
<div class="field">
{{ form.message.errors }}
<label for="id_message">Message:</label>
{{ form.message }}
</div>
<input type="submit" value="Submit">
</form>
</body>
</html>
URLConf Ticks
• There’s nothing “special” about URLconfs—like anything else in Django, they’re just Python
code. You can take advantage of this in several ways, as described in the sections that follow.
Streamlining Function Imports
from django.conf.urls.defaults import *
from mysite.views import hello, current_datetime
urlpatterns = patterns(‘ ’,
(r'^hello/$', hello),
(r'^time/$', current_datetime),
)
But as a Django application grows in complexity, its URLconf grows, too, and keeping those
imports can be tedious to manage. It’s possible to avoid that tedium by importing the views
module itself.
Note: from django.conf.urls.defaults import * is outdated as of Django 1.6 and was removed in
later versions. Instead, you should use from django.conf.urls import url or from django.urls import
path in modern Django projects.
URLConf Ticks
The updated code for the recent versions of Django:
from django.urls import path
from mysite.views import hello, current_datetime
urlpatterns = [
path('hello/', hello, name='hello'),
path('time/', current_datetime, name='current_datetime'),
]
.
[OR]
from django.urls import re_path
from mysite.views import hello, current_datetime, hours_ahead
urlpatterns = [
re_path(r'^hello/$', hello, name='hello'),
re_path(r'^time/$', current_datetime, name='current_datetime'),
]
Advantage: Simplifies imports, but still requires module import.
URLConf Ticks
Importing the Views Module:
Example:
from django.conf.urls.defaults import *
from mysite import views
urlpatterns = patterns(‘’,
(r'^hello/$', views.hello),
(r'^time/$', views.current_datetime),
)
Advantage: Simplifies imports, but still requires module import.
URLConf Ticks
urlpatterns = [
path('hello/', views.hello, name='hello'),
path('time/', views.current_datetime, name='current_datetime'),
]
URLConf Ticks
Using Strings to Specify View Functions
Django offers another way of specifying the view function for a particular pattern in the URLconf:
you can pass a string containing the module name and function name rather than the function
object itself.
Example
from django.conf.urls.defaults import *
urlpatterns = patterns(‘’,
(r'^hello/$', 'mysite.views.hello’),
(r'^time/$', 'mysite.views.current_datetime’),
)
Advantage: No need to import view functions; Django handles imports automatically.
Note: from django.conf.urls.defaults import * is outdated as of Django 1.6 and was removed in
later versions. Instead, you should use from django.conf.urls import url or from django.urls
import path in modern Django projects.
URLConf Ticks
The code in the recent version of Django:
from django.urls import path
urlpatterns = [
path('hello/', 'mysite.views.hello', name='hello'),
path('time/', 'mysite.views.current_datetime’, name='current_datetime’),
]
URLConf Ticks
• Factoring Out a Common View Prefix:
Example:
from django.conf.urls.defaults import *
urlpatterns = patterns('mysite.views’,
(r'^hello/$', 'hello’),
(r'^time/$', 'current_datetime’),
)
urlpatterns = [
path('hello/', views.hello, name='hello'),
path('time/', views.current_datetime, name='current_datetime'),
]
Including other URLconfs
If you intend your code to be used on multiple Django-based sites, you should consider
arranging your URLconfs in such a way that allows for “including.”
Purpose and Benefit
1. Purpose: Allows for modular organization of URL patterns by "including" URLconf modules
from different parts of the project.
2. Benefit: Enhances reusability and maintainability across multiple Django-based sites.
from django.conf.urls.defaults import *
urlpatterns = patterns(‘’,
(r'^weblog/', include('blog.urls')),
(r'^photos/', include(‘photos.urls’)),
)
Note: from django.conf.urls.defaults import * is outdated as of Django 1.6 and was removed
in later versions.
Including other URLconfs
The code in the recent versions of Django:
from django.urls import path, include
urlpatterns = [
path('weblog/', include('blog.urls')),
path('photos/', include('photos.urls’)),
]
Including other URLconfs
Continuing this example, here’s the URLconf mysite.blog.urls:
from django.conf.urls.defaults import *
urlpatterns = patterns(‘’,
(r'^(\d\d\d\d)/$', 'mysite.blog.views.year_detail’),
(r'^(\d\d\d\d)/(\d\d)/$', 'mysite.blog.views.month_detail’),
)
Including other URLconfs
Sample Request Handling
1. Request: /weblog/2007/
2. • First URLconf: r'^weblog/' matches.
3. • Action: Strips weblog/.
4. • Remaining URL: 2007/.
5. • Result: Matches r'^(\d\d\d\d)/$' in mysite.blog.urls.
Including other URLconfs
2. Request: /weblog//2007/ (with two slashes)
• First URLconf: r'^weblog/' matches.
• Action: Strips weblog/.
• Remaining URL: /2007/ (with leading slash).
• Result: Does not match any patterns in mysite.blog.urls.
Including other URLconfs
With these two URLconfs, here’s how a few sample requests would be
handled:
• /weblog/2007/: In the first URLconf, the pattern 'weblog/' matches. Because
it is an include(), Django strips all the matching text, which is 'weblog/' in this
case. The remaining part of the URL is 2007/, which matches the first line in
the mysite.blog. urls URLconf.