Skip to content

1. View

In Django, views are responsible for processing HTTP requests, fetching data from models, passing that data to templates, and returning HTTP responses. Advanced views typically involve using class-based views (CBVs), handling complex query parameters, working with forms, integrating third-party services, managing permissions, or using Django’s advanced features like mixins, decorators, and viewsets.

Below are several advanced examples of Django views.

1. Class-Based Views (CBVs) with Mixins

Class-Based Views provide more structure and reusable components. You can extend Django’s View class and use mixins to add functionality to your views.

Example: List and Create Views for a Blog App

from django.shortcuts import render
from django.http import HttpResponseRedirect
from django.urls import reverse
from django.views import View
from django.views.generic import ListView, CreateView
from .models import Post
from .forms import PostForm
# List View (CBV)
class PostListView(ListView):
model = Post
template_name = 'blog/post_list.html'
context_object_name = 'posts'
def get_queryset(self):
return Post.objects.filter(status='published').order_by('-created_at')
# Create View (CBV)
class PostCreateView(CreateView):
model = Post
form_class = PostForm
template_name = 'blog/post_form.html'
success_url = '/blog/'
def form_valid(self, form):
# Add custom logic before saving the form
form.instance.author = self.request.user
return super().form_valid(form)
  • Explanation:
    • PostListView is a ListView that displays a list of blog posts filtered by a status of ‘published’ and ordered by the created_at date.
    • PostCreateView is a CreateView that allows users to create new posts. It uses a PostForm form class and ensures that the author field is set to the currently logged-in user.

2. View with Multiple HTTP Methods (GET, POST)

You can handle multiple HTTP methods in a single view. This is useful for views that both render a form (GET) and process form submissions (POST).

Example: Handling a Contact Form

from django.shortcuts import render
from django.http import HttpResponse
from django.views import View
from .forms import ContactForm
class ContactView(View):
def get(self, request):
form = ContactForm()
return render(request, 'contact/contact_form.html', {'form': form})
def post(self, request):
form = ContactForm(request.POST)
if form.is_valid():
# Process the form data, send email, etc.
# For example, send email using form.cleaned_data['email']
return HttpResponse("Thank you for your message!")
return render(request, 'contact/contact_form.html', {'form': form})
  • Explanation:
    • The get method displays an empty contact form.
    • The post method processes the form when it’s submitted. If the form is valid, it sends a response thanking the user.

3. Using mixins for Reusability

Django provides several useful mixins for class-based views to reduce code duplication, such as LoginRequiredMixin, PermissionRequiredMixin, and UserPassesTestMixin.

Example: LoginRequiredMixin with Detail View

from django.contrib.auth.mixins import LoginRequiredMixin
from django.views.generic import DetailView
from .models import Post
class PostDetailView(LoginRequiredMixin, DetailView):
model = Post
template_name = 'blog/post_detail.html'
context_object_name = 'post'
login_url = '/login/' # Redirect to this URL if the user isn't logged in
  • Explanation:
    • The PostDetailView requires the user to be logged in. If the user is not logged in, they will be redirected to the /login/ page.
    • The LoginRequiredMixin is a common pattern for protecting views that require authentication.

4. Advanced Query Handling in Views

You may need to filter, sort, or paginate querysets dynamically based on user input or URL parameters.

Example: Advanced Filtering and Pagination

from django.core.paginator import Paginator
from django.shortcuts import render
from django.views import View
from .models import Post
class PostListView(View):
def get(self, request):
queryset = Post.objects.all()
# Filtering by category
category = request.GET.get('category', None)
if category:
queryset = queryset.filter(category__name=category)
# Sorting by date
sort_by = request.GET.get('sort_by', 'created_at')
queryset = queryset.order_by(sort_by)
# Pagination
paginator = Paginator(queryset, 5) # Show 5 posts per page
page_number = request.GET.get('page')
page_obj = paginator.get_page(page_number)
return render(request, 'blog/post_list.html', {'page_obj': page_obj})
  • Explanation:
    • The view fetches all posts initially but can filter by category and sort by a user-selected field (created_at, title, etc.).
    • Pagination is applied using Django’s Paginator class, displaying 5 posts per page. The current page is retrieved from the page GET parameter.

5. Form Handling with Custom Validation

Custom validation can be added to forms in the view to add business logic before saving data or to validate data from multiple forms.

Example: Form with Custom Validation in the View

from django.shortcuts import render
from django.http import HttpResponse
from django.views import View
from .forms import SignUpForm
class SignUpView(View):
def get(self, request):
form = SignUpForm()
return render(request, 'signup/sign_up.html', {'form': form})
def post(self, request):
form = SignUpForm(request.POST)
if form.is_valid():
email = form.cleaned_data['email']
if 'example.com' in email:
form.add_error('email', 'Emails from example.com are not allowed.')
return render(request, 'signup/sign_up.html', {'form': form})
# Process the valid form (save user, send confirmation, etc.)
return HttpResponse("You have signed up successfully!")
return render(request, 'signup/sign_up.html', {'form': form})
  • Explanation:
    • The post method includes custom validation to check whether the email domain is 'example.com'. If the email is from that domain, an error is added to the form, preventing submission.
    • If the form passes validation, you can proceed to save the user or handle further logic.

6. Using Django REST Framework with ViewSets

When working with APIs, Django REST Framework (DRF) makes it easier to work with class-based views. A viewset provides methods for handling standard CRUD operations like create, read, update, and delete.

Example: API ViewSet for Posts

from rest_framework import viewsets
from .models import Post
from .serializers import PostSerializer
class PostViewSet(viewsets.ModelViewSet):
queryset = Post.objects.all()
serializer_class = PostSerializer
def perform_create(self, serializer):
# Add custom logic before saving the post
serializer.save(author=self.request.user)
  • Explanation:
    • PostViewSet extends ModelViewSet and automatically provides CRUD functionality for Post objects. It uses PostSerializer to convert model data into JSON format.
    • The perform_create method is overridden to assign the current user as the author of the post before saving it to the database.

Example: URLs for the ViewSet

You need to register the PostViewSet in your URLs using DRF’s router:

from rest_framework.routers import DefaultRouter
from .views import PostViewSet
router = DefaultRouter()
router.register(r'posts', PostViewSet)
urlpatterns = router.urls

7. Handling Complex Permissions

You can add permission checks to class-based views to restrict access to specific users based on their roles.

Example: View with Custom Permission Class

from django.contrib.auth.mixins import LoginRequiredMixin
from django.views.generic import DetailView
from rest_framework.permissions import BasePermission
from .models import Post
class IsAuthor(BasePermission):
def has_object_permission(self, request, view, obj):
return obj.author == request.user
class PostDetailView(LoginRequiredMixin, DetailView):
model = Post
template_name = 'blog/post_detail.html'
context_object_name = 'post'
permission_classes = [IsAuthor]
def get_queryset(self):
return Post.objects.all()
  • Explanation:
    • IsAuthor is a custom permission class that ensures the user can only view the Post if they are the author of that post.
    • The PostDetailView is protected by both LoginRequiredMixin (to ensure the user is authenticated) and IsAuthor (to ensure they are the author of the post).