- Published on
Get to know useful Django features
- Authors
- Name
- K N Anantha nandanan
- @Ananthan2k
Get to know useful Django features
Django is a powerful web framework that makes it easy to build complex web applications. One of the things that makes Django so powerful is its ability to handle forms, formsets, inlines, filters, querysets, and templates. In this blog post, we're going to take a closer look at each of these topics and see how they can be used to build amazing web applications.
Forms
Forms are the most common way to collect user input in a web application. Django provides a powerful form framework that makes it easy to create forms and validate user input. In this section, we'll take a look at how to create a simple form and how to validate user input.
Creating a form
To create a form, we need to create a class that inherits from the ModelForm
class. The ModelForm
class is a subclass of the Form
class.
The ModelForm
class provides a set of helper methods that make it easy to create forms and validate user input. For example, the ModelForm
class provides a save()
method that saves the form data to the database. The ModelForm
class also provides a clean()
method that
validates user input. For example, let's take assume a Model called User
that has some fields. We can create a form for the User
model.
from django import forms
from .models import User
class UserForm(forms.ModelForm):
class Meta:
model = User
fields = ['first_name', 'last_name', 'email']
- The
Meta
class is used to define the model and fields that the form will be based on. You can exclude fields from the form by using theexclude
attribute instead of thefields
attribute. - There are other features that can be used to customize the form. For example, you can use the
widgets
attribute to specify the type of widget that should be used for each field. You can also use thelabels
attribute to specify the label for each field. - Furthermore, there are different form fields. For example, the
CharField
is used to represent a text field. TheEmailField
is used to represent an email field. TheDateField
is used to represent a date field. TheDateTimeField
is used to represent a date and time field etc. Let's take a look at how to use these fields, widgets, labels in our Form.
from django import forms
from .models import User
class UserForm(forms.ModelForm):
first_name = forms.CharField(label='First Name', max_length=100, widget=forms.TextInput(
attrs={
'class': 'form-control',
'placeholder': 'Enter your first name'
}
))
last_name = forms.CharField(label='Last Name', max_length=100, widget=forms.TextInput(
attrs={
'class': 'form-control',
'placeholder': 'Enter your last name'
}
))
email = forms.EmailField(label='Email', widget=forms.EmailInput(
attrs={
'class': 'form-control',
'placeholder': 'Enter your email'
}
))
class Meta:
model = User
fields = ['first_name', 'last_name', 'email']
exclude = ['date_joined']
- There are many other fields and widgets that can be used according to the need. You can refer to the documentation for more information.
How to use the form in a view ?
To use the form in a view, we need to create a view function that takes a request as an argument. The view function should return a response that contains the form. For example, let's create a view function that returns a form.
from django.shortcuts import render
from .forms import UserForm
def user_form_view(request):
form = UserForm()
return render(request, 'user_form.html', {'form': form})
- The
render()
function is used to render a template. Therender()
function takes three arguments. The first argument is the request. The second argument is the template name. The third argument is a dictionary that contains the context. The context is a dictionary that contains the variables that will be available in the template. In this case, the context contains the form variable. - The
user_form.html
template can be created as follows.
{% extends 'base.html' %} {% block content %}
<form method="POST">
{% csrf_token %} {{ form.as_p }}
<button type="submit" class="btn btn-primary">Submit</button>
</form>
{% endblock %}
- The
form.as_p
tag is used to render the form as a paragraph. Theform.as_table
tag is used to render the form as a table. Theform.as_ul
tag is used to render the form as an unordered list. - The
csrf_token
tag is used to render the CSRF token. The CSRF token is used to prevent Cross-Site Request Forgery attacks. The CSRF token is a hidden field that is used to validate the form. The CSRF token is automatically added to the form when themethod
attribute is set toPOST
. It's important to add the CSRF token to the form. Otherwise, the form will not be submitted because the CSRF token will not be validated. You can read more about CSRF tokens here.
How to validate user input ?
Now the above user_form_view
function is used to render the form. However, the form is not used to collect user input. To collect user input,
we need to use the request.POST
attribute. The request.POST
attribute is a dictionary that contains the form data. For example, let's
modify the user_form_view
function to collect user input.
from django.shortcuts import render
from .forms import UserForm
def user_form_view(request):
form = UserForm()
if request.method == 'POST':
form = UserForm(request.POST)
if form.is_valid():
form.save()
return render(request, 'user_form.html', {'form': form})
-
The
form.is_valid()
method is used to validate user input. If the user input is valid, theform.save()
method is used to save the form data to the database. If the user input is invalid, theform.errors
attribute is used to get the errors. -
Sometimes, you might want to get the data from the form without saving it to the database. In this case, you can use the
form.cleaned_data
attribute. Theform.cleaned_data
attribute is a dictionary that contains the form data. For example, let's modify theuser_form_view
function to get the data from the form without saving it to the database.
from django.shortcuts import render
from .forms import UserForm
def user_form_view(request):
form = UserForm()
if request.method == 'POST':
form = UserForm(request.POST)
if form.is_valid():
first_name = form.cleaned_data['first_name']
last_name = form.cleaned_data['last_name']
email = form.cleaned_data['email']
return render(request, 'user_form.html', {'form': form})
Note: The
form.cleaned_data
attribute is only available if theform.is_valid()
method returnsTrue
. And you can only use theget()
method to get the data from theform.cleaned_data
attribute. For example,first_name = form.cleaned_data.get('first_name')
.
How to set initial values for a form ?
Sometimes, you might want to set initial values for a form. For example, let's say you want to create a form that allows users to update their
profile or to help user fill-in less predicatable information, like his birthday which could be taken from the database, we can customize the form
to set the initial values for the fields. For example, let's modify the user_form_view
function to set the initial values for the form.
from django.shortcuts import render
from .forms import UserForm
def user_form_view(request):
form = UserForm()
if request.method == 'POST':
user = User.objects.get(id=request.user.id)
form = UserForm(request.POST)
if form.is_valid():
form.save()
else:
form = UserForm(initial={'birth_date': user.birth_date.strftime('%Y-%m-%d')})
return render(request, 'user_form.html', {'form': form})
- The
form = UserForm(initial={'birth_date': user.birth_date.strftime('%Y-%m-%d')})
line is used to set the initial value for thebirth_date
field.
Note: The
request.user
attribute is used to get the current user. Therequest.user
attribute is only available if the user is authenticated. You can read more about authentication here.
Formsets
Formsets are a way to manage multiple forms in a single view. They are particularly useful when you need to handle a large number of forms in a single view. For example, imagine you have a website that allows users to create a list of items. Instead of creating a separate form for each item, you can use a formset to handle all of the forms in a single view. Let's take a look at how to use formsets.
Preparing a formset
Let's say we have the User
model that we created in the previous section. We want to create a formset that allows users to add his/her social media
accounts. The User
model has the following fields.
class User(models.Model):
first_name = models.CharField(max_length=100)
last_name = models.CharField(max_length=100)
email = models.EmailField()
date_joined = models.DateTimeField(auto_now_add=True)
- We want to create a formset that allows users to add his/her social media accounts. The
SocialMediaAccount
model has the following fields.
class SocialMediaAccount(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
name = models.CharField(max_length=100)
url = models.URLField()
- The
SocialMediaAccount
model has a foreign key to theUser
model. Theuser
field is used to store the user that owns the social media account.
What I have to come to use is the inlineformset_factory
function to create a formset. The inlineformset_factory
function takes three arguments.
The first argument is the parent model. The second argument is the child model. For example, let's create a formset that allows users to add his/her social media accounts. Let's create a new view called user_formset_view
in the
views.py
file.
from django.shortcuts import render
from .forms import UserForm
from .models import User, SocialMediaAccount
def user_formset_view(request):
UserFormSet = inlineformset_factory(User, SocialMediaAccount, fields=('name', 'url'), extra=1,
can_delete=False)
if request.method == 'POST':
form = UserForm(request.POST)
formset = UserFormSet(request.POST)
if form.is_valid() and formset.is_valid():
user = form.save()
for form in formset:
social_media_account = form.save(commit=False)
social_media_account.user = user
social_media_account.save()
else:
form = UserForm()
formset = UserFormSet()
return render(request, 'user_formset.html', {'formset': formset}, {'form': form})
So what's happening here? Let me explain is step by step.
-
The
inlineformset_factory
function is used to create a formset. Theinlineformset_factory
function takes three arguments.- The first argument isthe parent model.
- The second argument is the child model.
- The
extra
argument is used to specify the number of extra forms that will be added to the formset. - The
can_delete
argument is used to specify whether the user can delete the forms in the formset. - The
fields
argument is used to specify the fields that will be displayed in the formset.
-
Then, we check if the request method is
POST
. If the request method isPOST
, we create aUserForm
instance and aUserFormSet
instance. -
Then, we check if the
UserForm
instance and theUserFormSet
instance are valid. If they are valid, we save theUserForm
instance to the database. Then, we loop through theUserFormSet
instance and save each form to the database. -
If the request method is not
POST
, we create aUserForm
instance and aUserFormSet
instance. -
Finally, we render the
user_formset.html
template and pass theUserFormSet
instance along with theUserForm
instance to the template.
What is difference between UserForm and UserFormSet?
When you create a form or formset object and pass it the request.POST
data,
Django will automatically extract the relevant data from the request and use it to populate the form or formset fields.
For example, when you create a form object using form = UserForm(request.POST)
, Django will extract the data from the request.POST
object that corresponds
to the fields in the UserForm, and use that data to populate the form. Similarly, when you create a formset object using formset = UserFormSet(request.POST)
,
Django will extract the data from the request.POST
object that corresponds to the fields in the UserFormSet and use that data to populate the formset.
Creating a formset template
Now that we have created a formset, let's create a template to display the formset. Let's create a new file called user_formset.html
in the templates
folder.
{% extends 'base.html' %} {% block content %}
<h1>User Formset</h1>
<form method="POST">
{% csrf_token %} {{ form.as_p }} {{ formset.management_form }} {% for form in formset %} {{
form.as_p }} {% endfor %}
<input type="submit" value="Submit" />
</form>
{% endblock %}
So what's happening here? Let me explain is step by step.
- We extend the
base.html
template. - Then, we display the
UserForm
instance using theform.as_p
template tag. - Then, we display the
UserFormSet
management form using theformset.management_form
template tag. - Then, we loop through the
UserFormSet
instance and display each form using theform.as_p
template tag. - Finally, we display a submit button.
This is a very basic implementation of a formset. You can use the same approach to create more complex formsets.
Inlines
In django admin, out of the box has a lot of features and it's pretty easy to use. But if you want to customize the admin site, you can do that too. One of those is the need to add or edit related objects on the same page as the parent object. This is called inlines.
Creating an inline
Let's use the User
model and the SocialMediaAccount
model to create an inline. Assuming we have registered the User
model and the SocialMediaAccount
model
in the admin site, let's create a new class called SocialMediaAccountInline
in the admin.py
file.
from django.contrib import admin
from .models import User, SocialMediaAccount
class SocialMediaAccountInline(admin.TabularInline):
model = SocialMediaAccount
extra = 1
@admin.register(User)
class UserAdmin(admin.ModelAdmin):
search_fields = ('first_name', 'last_name', 'email')
list_display = ('first_name', 'last_name', 'email')
inlines = [SocialMediaAccountInline]
This will add the SocialMediaAccount
model as an inline to the User
model in the admin site.
Different types of inlines
StackedInline
- Displays the inline in a stacked format.TabularInline
- Displays the inline in a tabular format.
Querysets
Querysets are the core of Django's ORM. Querysets allow you to read data from the database, filter data, order data, and much more. Querysets are lazy. This means that querysets are not evaluated until they are needed. This is a very important concept to understand. So let's dive into it.
Creating a queryset
Let's play around with just the User
model just to get a feel for querysets.
- Get all users
from .models import User
users = User.objects.all()
- Get a single user
from .models import User
user = User.objects.get(id=1)
- Okay so we gave the
get()
method theid
of the user we want to get. But what if we want to get the user by email? We can do that too. Better yet, what if we want to get the user through a mixture of fields? It's possible.
from .models import User
user = User.objects.get(
first_name='John',
last_name='Doe',
created_at__year=2020,
)
Filtering
We could only have limited use of get()
if we had to get a single user. But what if we want to get multiple users? We can do that too.
To get more fancier and chain different filters, we can use the filter()
method.
from .models import User
users = User.objects.filter(
first_name='John',
last_name='Doe',
created_at__year=2020,
)
Ordering
We can order the querysets. Ordering is done by passing the field name to the order_by()
method.
from .models import User
users = User.objects.order_by('first_name')
Limiting
We can limit the querysets. Limiting is done by passing the number of items to the all()
method. Most often done with slicing.
from .models import User
users = User.objects.all()[:5]
Counting
We can count the querysets. Counting is done by calling the count()
method. This is very useful when we want to get the number
of items in a queryset.
from .models import User
users = User.objects.count()
Use Q objects
In django we can use Q
objects to combine filters. Let's see how we can do that.
from django.db.models import Q
# Find all users who have either 'John' as first name or 'Doe' as last name
users = User.objects.filter(Q(first_name='John') | Q(last_name='Doe'))
# Find all users who have 'John' as first name and 'Doe' as last name
users = User.objects.filter(Q(first_name='John') & Q(last_name='Doe'))
# Find all users who have last name 'Doe' but not 'John' as first name
users = User.objects.filter(Q(last_name='Doe') & ~Q(first_name='John'))
# Find all users who have last name 'Doe' or first name 'John' but not both
users = User.objects.filter(Q(last_name='Doe') | Q(first_name='John')).exclude(first_name='John', last_name='Doe')
Use F objects
In django we can use F
objects to compare fields.
from django.db.models import F
# Find all users whose first name is the same as their last name
users = User.objects.filter(first_name=F('last_name'))
# Find all users whose age is greater than the age of their manager
users = User.objects.filter(age__gt=F('manager__age'))
# Find all users whose age is at least twice the age of their manager
users = User.objects.filter(age__gte=F('manager__age')*2)
# Find all users whose birth date is before their registration date
users = User.objects.filter(birth_date__lt=F('registration_date'))
# Find all users whose last login date is more recent than their registration date
users = User.objects.filter(last_login__gt=F('registration_date'))
Use Q objects and F objects together
We can also use Q objects and F objects together. In very complex queries, this is very useful.
from django.db.models import Q, F
# Find all users whose first name is the same as their last name and their age is greater than 18
users = User.objects.filter(Q(first_name=F('last_name')) & Q(age__gt=18))
Reverse relationships
In django it's pretty straightforward to get objects from parent to child. But what if we want to get objects from child to parent? There is a way to accomplish that.
Let's use the User
model and the SocialMediaAccount
model to get objects from child to parent.
from .models import User, SocialMediaAccount
# Get all social media accounts of a user
user = User.objects.get(id=1)
social_media_accounts = user.social_media_accounts.all()
What if we want to get all users of a social media account? There is a method to access attributes of the a parent object from a child object.
Let's consider the example of Building
and Room
models. A building can have many rooms. But a room can only have one building.
from .models import Building, Room
# Get all rooms of a building
building = Building.objects.get(id=1)
rooms = building.room_set.all()
# Get the building of a room
room = Room.objects.get(id=1)
building = room.building
- But if the relationship is a ManyToManyField, then we can use
through
to get the related objects, or we can userelated_name
to get the related objects.
Let's consider the example of User
and Group
models. A user can be in many groups. And a group can have many users.
from .models import User, Group
users = User.objects.filter(name='John', user_groups=g.id)
- Here we are using
user_groups
as therelated_name
of theManyToManyField
in theUser
model.
Note: If you want to get the related objects through a ManyToManyField, then you can use
through
to get the related objects, or you can userelated_name
to get the related objects.
Templates
In django we can use templates to render dynamic content. They are very powerful and easy to use. The syntax is very similar to HTML. It's also called Django Template Language (DTL) it's pretty similar to Jinja2.
Let's go through set up and some basic syntax.
-
First we need to create a template file. Let's create a
templates
folder in the root of our project. Then create ausers
folder inside thetemplates
folder. Then create aindex.html
file inside theusers
folder. -
Then we need to add the
TEMPLATES
setting in thesettings.py
file.
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',
'django.contrib.messages.context_processors.messages',
],
},
},
]
Note: We need to add the
DIRS
setting to tell django where to look for the templates.
- To make use of the templates that we create, we need to create a view. Let's create a
views.py
file in theusers
folder.
from django.shortcuts import render
from .models import User
def index(request):
users = User.objects.all()
return render(request, 'users/index.html', {'users': users})
- Then in the
urls.py
file of theusers
app, we need to add theindex
view.
from django.urls import path
from . import views
urlpatterns = [
path('', views.index, name='index'),
]
- In the
index.html
file, we can use theusers
variable that we passed to the template.
{% for user in users %}
<p>{{ user.first_name }} {{ user.last_name }}</p>
{% endfor %}
Template tags
In django we can use template tags to do some logic in the template. I won't be covering all the template tags, just the ones that is commonly used.
if
tag
{% if user.age > 18 %}
<p>{{ user.first_name }} {{ user.last_name }} is an adult</p>
{% else %}
<p>{{ user.first_name }} {{ user.last_name }} is a minor</p>
{% endif %}
for
tag
{% for user in users %}
<p>{{ user.first_name }} {{ user.last_name }}</p>
{% endfor %}
url
tag
<a href="{% url 'index' %}">Home</a>
Note: We can use the
url
tag to get the url of a view. We need to pass the name of the view as the argument.
static
tag
<link rel="stylesheet" href="{% static 'css/style.css' %}" />
Note: We can use the
static
tag to get the url of a static file. We need to pass the path of the static file as the argument. By default django looks for the static files in thestatic
folder in the root of the project.
block
tag
{% block content %}
<h1>Home</h1>
{% endblock %}
Note: We can use the
block
tag to define a block in the template. Every template that extends another template must have ablock
tag. If we don't have ablock
tag, then django will throw an error.
extends
tag
{% extends 'base.html' %}
Pro Tip: Every template could be extended from a
base.html
file. This is a good practice. We can use theblock
tag to override the blocks in thebase.html
file.
Let's demonstrate how we can use the block
and extends
tags. Remember block
tag is used to define a block in the template,
which means when a child template extends a parent template, then the child template can override the blocks in the parent template or
add content inside that block thereby extending the parent template.
This is a great way to reuse the code, the child template is able to customize specific parts of the parent template. Without having to copy the whole template again and again.
- First we need to create a
base.html
file in thetemplates
folder. Then we need to add theblock
tag in thebase.html
file.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Base</title>
</head>
<body>
<header>
<nav>
<ul>
<li><a href="{% url 'index' %}">Home</a></li>
<li><a href="{% url 'users:index' %}">Users</a></li>
</ul>
</nav>
</header>
<main>{% block content %} {% endblock %}</main>
</body>
</html>
- Then we need to create a
index.html
file in theusers
folder. Then we need to add theextends
tag in theindex.html
file.
{% extends 'base.html' %} {% block content %}
<h1>Home</h1>
{% endblock %}
Note: We need to add the
block
tag in thebase.html
file and theextends
tag in theindex.html
file.
- This means the
index.html
file extends thebase.html
file. So theindex.html
file will have the content of thebase.html
file and it's own content embedded in theblock
tag.
Template filters
In django we can use template filters to modify the data in the template. I won't be covering all the template filters, just the ones that is commonly used.
date
filter
<p>{{ user.created_at|date }}</p>
Note: We can use the
date
filter to format the date. We can pass the format as the argument.
time
filter
<p>{{ user.created_at|time }}</p>
Note: We can use the
time
filter to format the time. We can pass the format as the argument.
length
filter
<p>{{ user.first_name|length }}</p>
Note: We can use the
length
filter to get the length of a string.
- There are many other filters that we can use in django. We can check the documentation for more information.
Django Cache
In the world of web development, caching is a very important topic. Caching is a way to store data in a temporary storage so that we can access it faster. We need to use caching when we have data that is not changing frequently. For example, if we have a list of users, then we can cache the list of users so that we don't have to query the database every time we need the list of users. This will improve the performance of our application.
Django provides a very flexible caching system. We can use different caching backends. The integration with the caching system is very easy. We can use
the caching system in our views, templates, models, etc. Let's use Redis
as the caching backend. Since Redis
is an in-memory database, it is very fast and
pretty popular in the industry.
- First we need to install
django-redis
andredis
packages.
pip install django-redis redis
- Then we need to add the
django-redis
package to theINSTALLED_APPS
in thesettings.py
file.
INSTALLED_APPS = [
...
'django_redis',
]
- Then we need to add the
CACHES
setting in thesettings.py
file.
CACHES = {
"default": {
"BACKEND": "django_redis.cache.RedisCache",
"LOCATION": "redis://6379",
"OPTIONS": {
"CLIENT_CLASS": "django_redis.client.DefaultClient",
}
}
}
Note: We need to add the
CACHES
setting in thesettings.py
file. We need to pass theBACKEND
andLOCATION
as the arguments.
Let's start using the caching system in our application. We will use the caching system in our index
view.
- First we need to import the
cache
from thedjango.core.cache
module.
from django.core.cache import cache
- Then we need to add the
cache
decorator to theindex
view.
@cache_page(60 * 15)
def index(request):
users = User.objects.all()
return render(request, 'users/index.html', {'users': users})
So what's happening here? We are using the cache_page
decorator to cache the index
view. We are passing the 60 * 15
as the argument. This means
the index
view will be cached for 15 minutes. So if we access the index
view within 15 minutes, then the view will be served from the cache. If we access
the index
view after 15 minutes, then the view will be served from the database.
- The next thing we need to do is to add the
cache
tag in theindex.html
file.
{% load cache %}
- Then we need to add the
cache
tag in theindex.html
file.
{% cache 60 * 15 users %}
<ul>
{% for user in users %}
<li>{{ user.first_name }} {{ user.last_name }}</li>
{% endfor %}
</ul>
{% endcache %}
So what's happening here? We are using the cache
tag to cache the users
queryset. We are passing the 60 * 15
as the argument. This means
the users
queryset will be cached for 15 minutes. So if we access the index
view within 15 minutes,
then the users
queryset will be served from the cache. If we access the index
view after 15 minutes, then the users
queryset will
be served from the database.
NOTE: the purpose of caching in template and view is different. In view, we are caching so that we don't recall the database every time we access the view. In template, we are caching so that we don't recall the database every time we access the template, only if the data is not altered.
Django Pagination
Django provides a very easy way to paginate the data. We can use the Paginator
class to paginate the data. Let's see how we can use the Paginator
class
to paginate the data.
- First we need to import the
Paginator
class from thedjango.core.paginator
module.
from django.core.paginator import Paginator
- Then we need to create a
Paginator
object and pass theusers
queryset and theper_page
as the arguments.
paginator = Paginator(users, 10)
- Then we need to get the
page
number from therequest.GET
dictionary.
page = request.GET.get('page')
- Then we need to get the
page
object from thepaginator
object.
page_obj = paginator.get_page(page)
- Then we need to pass the
page_obj
queryset to therender
function.
return render(request, 'users/index.html', {'page_obj': page_obj})
- Then we need to add the
page_obj
to theindex.html
file.
{% if page_obj.has_previous %}
<a href="?page={{ page_obj.previous_page_number }}">Previous</a>
{% endif %} {% for page in page_obj.paginator.page_range %}
<a href="?page={{ page }}">{{ page }}</a>
{% endfor %} {% if page_obj.has_next %}
<a href="?page={{ page_obj.next_page_number }}">Next</a>
{% endif %}
- Then we need to add the
page_obj
to theindex.html
file.
{% for user in page_obj %}
<li>{{ user.first_name }} {{ user.last_name }}</li>
{% endfor %}
Django Filtersets
Django provides a very easy way to filter the data. We can use the FilterSet
class to filter the data. Let's see how we can use the FilterSet
class.
This acts more like the detailed search functionality. We can filter the data based on the fields.
- First we need to install the
django-filter
package.
pip install django-filter
- Then we need to add the
django-filter
package to theINSTALLED_APPS
in thesettings.py
file.
INSTALLED_APPS = [
...
'django_filters',
]
- Then we need to create a
UserFilter
class and inherit theFilterSet
class.
from django_filters import FilterSet
class UserFilter(FilterSet):
class Meta:
model = User
fields = ['first_name', 'last_name']
- Then we need to add the
UserFilter
class to theindex
view.
def index(request):
users = User.objects.all()
user_filter = UserFilter(request.GET, queryset=users)
return render(request, 'users/index.html', {'user_filter': user_filter})
- Then we need to add the
user_filter
to theindex.html
file.
<form action="" method="GET">
{{ user_filter.form }}
<button type="submit">Filter</button>
</form>
- That is it. Now we can filter the data based on the fields.
Conclusion
In this post, I have covered some important and useful features of Django, like Django forms, formsets, Django caching, Django pagination, and Django filtersets. I hope you have enjoyed this post. These are the features I have used throughout my Django projects. I only provided simple examples to get an idea of how these features work. There are other features like Django signal, messages, logging, etc. When I get to use these features, I will write a post about them.