How to use Django views

How to use Django views

With the Django database and models set up to manage your application’s data, the next step is to connect this data to the user interface.

This is where views come into play. They define the logic and structure behind the web pages, determining how data is processed and displayed to users.

What is a view in Django?

In Django, views are an essential component that handle the logic of how your application responds to user requests.

Simply put, a view takes a web request, processes it, and returns a response – often in the form of a rendered HTML page. Views act as a bridge between the application’s data, managed by models, and its presentation, handled by Django templates.

Types of views in Django

There are two primary types of views in Django: Function-Based Views (FBVs) and Class-Based Views (CBVs). Both serve the same purpose but offer different ways of organizing code.

Function-Based Views (FBVs)

Function-Based Views are simple Python functions to handle HTTP requests and return responses. They are intuitive and ideal where you need more control over every aspect of the request and response lifecycle.

Here’s an example of a simple FBV that renders an HTML template:

from django.shortcuts import render

# Function-based view
def homepage(request):
    return render(request, 'homepage.html')

In this example:

  • request – represents the HTTP request object containing metadata about the user’s request.
  • render – Combines the homepage.html template with context data if provided and returns an HttpResponse object.

FBVs are easy to understand and implement, but can lead to bloated functions with complex logic if not carefully managed, especially when handling tasks like forms, authentication, or reusable patterns.

Class-Based Views (CBVs)

CBVs, on the other hand, utilize the principles of inheritance and encapsulation to create more structured and reusable views. They let developers take advantage of Django’s built-in generic views and easily override or extend methods for customization.

Built-in generic views like ListView and DetailView reduce boilerplate code by providing ready-made logic for tasks like rendering object lists, details, forms, and more.

Here’s an example of a CBV that performs the same function as the previous FBV:

from django.views.generic import TemplateView

# Class-based view
class HomePageView(TemplateView):
    template_name = 'homepage.html'

In this example:

  • TemplateView – A built-in generic view that renders a template.
  • template_name – specifies the template file to render, just like in the FBV example.

To use this CBV in the URL configuration, you’ll need to include the .as_view() method when adding it to urls.py:

from django.urls import path
from .views import HomePageView

urlpatterns = [
    path('', HomePageView.as_view(), name='home'),
]

When to Use FBVs vs. CBVs

  • Use FBVs when you need simplicity and full control over your view logic. They are often more intuitive for small views or custom logic that doesn’t fit into Django’s predefined view patterns.
  • Use CBVs when you want to follow Don’t Repeat Yourself (DRY) principles and reuse existing logic. CBVs are ideal when your views grow in complexity, such as when handling forms, paginated data, or standard CRUD operations.

Both FBVs and CBVs are integral to Django, and choosing between them depends on your project’s requirements and your personal preference.

For inspirations, some developers prefer to start with FBVs for prototyping or small projects and switch to CBVs as the project scales or when they need more structure and reusability.

Built-in generic views in Django

Django’s built-in generic views provides a way to handle repetitive patterns like displaying lists, managing forms, and handling CRUD operations with minimal boilerplate code.

Here are some commonly used ones:

  • DetailView – displays a detail page for a single object.
  • ListView – renders a list of objects.
  • CreateView – handles the creation of a new object and displays a form.
  • UpdateView – manages updating an existing object.
  • DeleteView – provides a form to delete an existing object.
  • TemplateView – renders a static template.
  • RedirectView – redirects to a different URL.
  • FormView – displays a form and processes it upon submission.

These views streamline many operations, so that developers can handle repetitive tasks with minimal code.

How to Customize Django Views

Customizing Django views typically involves adding custom logic for handling data, interacting with models, and returning specific responses based on the user’s actions.

Customizing FBVs

You can add logic before or after rendering a template, interact with models, handle forms, or return custom responses like JSON. Here’s an example of customizing an FBV for handling both GET and POST requests:

from django.http import HttpResponse
from django.shortcuts import render
from .models import MyModel

def my_custom_view(request):
    if request.method == 'POST':
        # Handle POST request logic
        data = request.POST['data']
        # Do something with the data, e.g., saving to the database
        MyModel.objects.create(data_field=data)
        return HttpResponse("Data Saved!")

    # Additional custom logic for GET requests
    context = {'items': MyModel.objects.all()}
    return render(request, 'my_template.html', context)

In the above snippet, POST extracts data from the form, processes it – in this case, saving it to the database – and returns a response. Meanwhile, GET requests retrieve all items from the database, send them to the template, and render the page.

You can also use decorators like @login_required or custom ones for specific behavior, such as access control. For instance:

from django.contrib.auth.decorators import login_required

@login_required
def my_protected_view(request):
    # This view is only accessible to logged-in users
    return HttpResponse("Hello, authenticated user!")

Customizing CBVs

CBVs offer a structured way to customize views by overriding methods, such as get() and post(). In the following example, we demonstrate how to customize CBVs for different request methods:

from django.views import View
from django.http import HttpResponse
from .models import MyModel

class MyCustomView(View):
    def get(self, request):
        # Custom logic for GET request
        items = MyModel.objects.all()
        return render(request, 'my_template.html', {'items': items})
    
    def post(self, request):
        # Custom logic for POST request
        data = request.POST['data']
        MyModel.objects.create(data_field=data)
        return HttpResponse("Data Saved!")

The above snippet uses a basic class-based view to handle both GET and POST requests, making it easier to implement custom behavior for each request type

Django’s CBVs also provide built-in functionality for common operations like listing objects or creating a form. You can customize their behavior by overriding class methods like get_queryset():

from django.views.generic import ListView
from .models import MyModel

class MyFilteredListView(ListView):
    model = MyModel
    template_name = 'filtered_list.html'
    
    def get_queryset(self):
        # Customize the queryset to only include certain items
        return MyModel.objects.filter(active=True)

In the above example, the view customizes the queryset by filtering the items it returns, so only active entries are displayed.

URL Configuration for Django Views

Let’s look at how a simple project might set up URL patterns:

  1. Project-Level URLs (myproject→urls.py)
from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),  # Admin site
    path('', include('myapp.urls')),  # Include app-level URLs for "myapp"
]
  • path() – maps URL patterns to views or other URL configurations.
  • admin.site.urls – routes requests to Django’s built-in admin interface.
  • include() – delegates routing to the app-level urls.py file for modular URL management.
  1. App-Level URLs (myproject→myapp→urls.py)
from django.urls import path
from . import views

urlpatterns = [
    path('', views.homepage, name='home'),  # Maps the root URL to the homepage view
    path('about/', views.about, name='about'),  # Maps "/about/" to the about view
]
  • The root URL (represented by ‘ ‘) is mapped to the homepage view.
  • The /about/ URL is mapped to the about view.

Adding FBVs to URL Patterns

Here’s how the corresponding views might look in views.py for the above URL configuration:

from django.shortcuts import render

def homepage(request):
    return render(request, 'homepage.html')

def about(request):
    return render(request, 'about.html')

The FBVs, homepage and about, are linked to URL patterns in the app-level urls.py, ensuring the correct view is called for each URL: http://example.com/ and http://example.com/about/.

Adding CBVs to URL Patterns

You can also map URLs to CBVs, which are handled slightly differently. Here’s an example:

from django.urls import path
from .views import HomePageView, AboutPageView

urlpatterns = [
    path('', HomePageView.as_view(), name='home'),
    path('about/', AboutPageView.as_view(), name='about'),
]

And the corresponding class-based views in views.py:

from django.views.generic import TemplateView

class HomePageView(TemplateView):
    template_name = 'homepage.html'

class AboutPageView(TemplateView):
    template_name = 'about.html'

The .as_view() method links the class-based views to the URL patterns.

Handling HTTP Methods with views

Here’s how FBVs and CBVs handle HTTP methods differently:

Using FBVs to handle HTTP methods

FBVs handle HTTP methods by checking the request method explicitly using request.method. You can define custom logic for each method, like GET and POST within the same function:

from django.http import HttpResponse
from django.shortcuts import render
from .models import MyModel

def my_view(request):
    if request.method == 'GET':
        # Logic for GET requests
        items = MyModel.objects.all()
        return render(request, 'my_template.html', {'items': items})
    elif request.method == 'POST':
        # Logic for POST requests
        data = request.POST.get('data')
        MyModel.objects.create(data_field=data)
        return HttpResponse("Data saved!")
    else:
        return HttpResponse("Unsupported HTTP method", status=405)

Here, request.method contains the HTTP method – GET or POST – as a string. However, you need to handle unsupported methods explicitly.

Using CBVs to handle HTTP methods

CBVs simplify handling HTTP methods by providing dedicated methods for each type of request. Django automatically dispatches incoming requests to the appropriate method, eliminating the need for manual checks as in FBVs.

from django.views import View
from django.http import JsonResponse

class ExampleView(View):
    def get(self, request):
        return JsonResponse({'message': 'This is a GET response'})

    def post(self, request):
        data = request.POST.get('data', None)
        return JsonResponse({'message': f'Received POST with data: {data}'}, status=201)

    def delete(self, request):
        return JsonResponse({'message': 'DELETE request handled'}, status=204)

Each method, such as get() and post(), is a separate function, making the logic clean and modular. If a method is not defined, Django responds with 405 Method Not Allowed automatically.

Conclusion

Django views are a powerful tool for processing requests and delivering responses. FBVs provide simplicity and control, ideal for smaller tasks, while CBVs offer structure and reusability, perfect for complex logic.

Understanding how to handle HTTP methods and customize views lets developers build efficient, scalable applications.

By leveraging Django’s built-in tools like generic views and method dispatching, you can streamline project development, maintain clean code, and focus on creating great user experiences.

Django views FAQ

What’s the difference between FBV and CBV in Django?

FBVs are simple functions for handling HTTP requests, ideal for plain views. CBVs use object-oriented programming, offering inheritance and built-in tools for complex tasks like CRUD. FBVs are easier to learn but less reusable, while CBVs provide better structure and flexibility at the cost of a steeper learning curve.

When should I use FBVs over CBVs?

Use FBVs for simple, one-off views with custom logic that don’t align with standard CRUD patterns. They’re ideal for API endpoints, webhook handlers, or unique page logic where simplicity and clarity are key. FBVs are also an excellent starting point for beginners learning Django’s view system.

Can I customize generic views in Django?

Yes, you can customize Django’s generic views by overriding their built-in methods like get_queryset(), get_context_data(), or form_valid(). You can also add mixins for additional functionality or modify attributes, like template_name, model, and context_object_name to suit your specific needs.

Author
The author

Andzelika D.

Andzelika is a Content Writer and Editor with over 5 years of experience in the digital marketing industry. With passion for technology and the art of the written word, she loves to combine the two worlds and produce actionable content.

Author
The Co-author

Ariffud Muhammad

Ariffud is a Technical Content Writer with an educational background in Informatics. He has extensive expertise in Linux and VPS, authoring over 200 articles on server management and web development. Follow him on LinkedIn.