DetailView in Django: How to display a detail view
Content Index
- What is DetailView and what is it used for in Django?
- ⚖️ CBV vs FBV: the natural evolution
- Key advantages of using DetailView
- Create the function in the view, views.py of our application
- Create the route at the application level
- ⚙️ How to create a DetailView in Django
- Configure the route in urls.py
- Create the template
- How DetailView works internally
- ⚙️ Automatic 404 error handling
- Customization and useful tricks
- Integrating DetailView with the rest of the CRUD
- Complete Example of DetailView
- ❓ Frequently Asked Questions (FAQ)
- Conclusion
Once we know how to do file upload, we're going to create one of the fundamental CRUD processes in our Django application, which is to display a detail page (the Read or show); for this, we'll need to follow 3 steps:
- Create the function in the view, views.py of our application.
- Create the route at the application level.
- Create the template.
one of the first tasks I had to solve when using Django was displaying the complete information of a record: the typical "detail" within the CRUD flow. Initially, I did it with a Function-Based View (FBV), but I soon discovered that Django offers a more elegant and reusable way: the DetailView, and this is a fundamental difference we have in Django when compared to other frameworks like Laravel, which is that we have two ways to return views.
In this article, I'll teach you, from experience, how to switch from a manual view to a Class-Based View (CBV), what its advantages are, and how to customize it with real code.
What is DetailView and what is it used for in Django?
DetailView is one of the generic Class-Based Views (CBV) included in Django.
Its purpose is simple: to display the detail of a single object from a model.
When I used the manual version, my function looked like this:
def show(request, pk): product = get_object_or_404(Product, id=pk) return render(request, 'show.html', {'product': product})This function works perfectly, but over time I discovered that I could replace that entire block with just a few lines thanks to DetailView.
⚖️ CBV vs FBV: the natural evolution
Function-Based Views (FBV) are ideal for starting: total control, explicit logic, and clear learning.
However, as the project grows, maintaining each manual view becomes tedious.
DetailView, being a CBV, allows you to inherit common behaviors, reduce repeated code, and keep the architecture clean.
Key advantages of using DetailView
- Shorter and easier-to-maintain code.
- Automatic handling of 404 errors.
- Pre-configured context and template.
- Compatible with mixins and advanced customization.
Create the function in the view, views.py of our application
def show(request,pk):
product = get_object_or_404(Product, id=pk)
"""try:
product = Product.objects.get(pk=pk)
except Product.DoesNotExist:
#return HttpResponse(status=404)
return HttpResponseNotFound()"""
return render(request, 'show.html', { 'product' : product })The function above simply searches for a record (Product in this case) given the pk; for this, we use the function called get_object_or_404, which searches for a record, and if it doesn't exist, it returns a 404 page; we can also do this manually:
try:
product = Product.objects.get(pk=pk)
except Product.DoesNotExist:
#return HttpResponse(status=404)
return HttpResponseNotFound()Which searches for a record, and if it doesn't exist, it returns a 404 exception, but get_object_or_404 does all that for us.
Create the route at the application level
For the route, we create it with a parameter called pk of integer type and give it a name.
app_name="gestion"
urlpatterns = [
path('',views.index),
path('detail/<int:pk>',views.show, name="show"),
]⚙️ How to create a DetailView in Django
To use DetailView, which is a Class-Based View instead of the function-based one we used before, you need to define a class in your views.py file:
from django.views.generic import DetailView
from .models import Product
class ProductDetailView(DetailView):
model = Product
template_name = 'show.html'
context_object_name = 'product'This class does the same as your show function, but automatically. Django searches for the object based on the pk or slug it receives from the URL.
Configure the route in urls.py
from django.urls import path
from .views import ProductDetailView
urlpatterns = [
path('detail/<int:pk>/', ProductDetailView.as_view(), name='show'),
]Here pk will be passed internally to the view, without you having to handle get_object_or_404.
Create the template
In our template, we display the content, the usual: the title, price, category, and description:
{% extends "base.html" %}
{% block title %}
{{product.title}}
{% endblock title %}
{% block content %}
<h1>{{product.title}}</h1>
<p>{{product.price}}$</p>
<p>{{product.category.title}}</p>
<p>{{product.description}}</p>
{% endblock %}The product context comes ready thanks to context_object_name. If you don't define it, Django will use the lowercase model name by default.
How DetailView works internally
When a request arrives, Django:
- Gets the defined model (Product).
- Searches for the object corresponding to the pk in the URL.
- If it doesn't find it, it automatically raises a 404 error.
- Renders the specified template with the context.
I used to do all this manually with get_object_or_404, but now Django handles the entire process.
⚙️ Automatic 404 error handling
If the object doesn't exist, DetailView raises Http404 without you having to wrap the logic in a try/except block.
This saves several lines of repeated code and helped me keep the views cleaner.
Customization and useful tricks
Sometimes you need to add extra data to the context (for example, related products or statistics).
You can do this by overriding the get_context_data() method:
class ProductDetailView(DetailView):
model = Product
template_name = 'show.html'
context_object_name = 'product'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['related'] = Product.objects.filter(category=self.object.category).exclude(pk=self.object.pk)
return contextThis allowed me to display similar products on the same page, without modifying the main template.
Integrating DetailView with the rest of the CRUD
DetailView is just one part of the set of generic views:
- ListView → displays lists.
- CreateView → creates records.
- UpdateView → updates records.
- DeleteView → deletes records.
Together they allow you to build a complete CRUD in minutes.
Complete Example of DetailView
# views.py
from django.views.generic import DetailView
from .models import Product
class ProductDetailView(DetailView):
model = Product
template_name = 'show.html'
context_object_name = 'product'
# urls.py
from django.urls import path
from .views import ProductDetailView
urlpatterns = [
path('product/<int:pk>/', ProductDetailView.as_view(), name='product_detail'),
]
<!-- show.html -->
<h1>{{ product.title }}</h1>
<p>{{ product.description }}</p>
<p>Precio: {{ product.price }}$</p>And with that, you have a functional and clean detail view.
❓ Frequently Asked Questions (FAQ)
1. How to customize the context in a DetailView?
Override the get_context_data method and add your custom variables.
2. What to do if the object is not found?
Django handles this automatically by returning a 404 error.
3. Can I use DetailView with related models?
Yes, you can access the relationships from the object (self.object) or add additional queries to the context.
Conclusion
In my case, switching from a Function-Based View to DetailView was an immediate improvement: less code, fewer errors, and a more professional structure.
DetailView allows you to display a model's data with just a few lines, leveraging the full power of Django's generic view system.
If you're used to using functions like show() with get_object_or_404, this change will feel like a relief.
With this, we can generate a basic cycle to display the content of a record: in summary, we create a route to pass an ID, search for the record, and display it in a template.
The next step is static file handling.
I agree to receive announcements of interest about this Blog.
We are going to generate a detail page or template to show the detail of a product in our application in Django, and you will learn how to create routes with parameters and the get_object_or_404 function.