How to get a single object in Django (A complete guide for function and class based views)
Sometimes, it would make sense to retrieve a single object from the database and display it to a user.
For example, you would retrieve a single object when dealing with a product, an article, a list in a to-do list, a category, a student, a subject, etc. The main goal being; to display detailed information about that single object.
There are two ways of retrieving objects from the database in Django:
- Through static and more manual approaches.
- Through dynamic approaches.
You can use the get() method to retrieve a single unique object from the database in Django. Another approach is to use the filter() method coupled with the .first() method– filter().first().
However, you would have to get each object stored in the database, handle the exceptions, and display each object to the user. A more efficient, dynamic, and straightforward way to retrieve a single object is to use the get_object_or_404() method or the generic DetailView in class based views. The method and the view will handle exceptions when retrieving objects in Django.
Let’s see in detail, with an example, how to retrieve an object from the database using the get(), filter(), and all() methods in Django.
But first, let’s create a Django project that we’ll use for demonstration. The project should be simple. You can jump to the first section if you already have a Django project.
Create an environment folder to store all your Python environments if you do not have one.
mkdir ~/.virtualenvs
Create a new virtual environment for your Django project
python -m venv ~/.virtualenvs/example_project_env
Activate the virtual environment
source ~/.virtualenvs/example_project_env/bin/activate
Install Django in your newly created virtual environment
pip install django
You can specify a specific Django version to install using 2 double equal signs, ==
pip install django==4.0
Create a project folder to store all your Django project files. I prefer the Desktop directory.
mkdir ~/Desktop/example_project
You can give the project directory any name you want.
Navigate into the new Django project folder
cd ~/Desktop/example_project
Create a new Django project
django-admin startproject exampleProject .
Create an app called student, or anything related to your project
python manage.py startapp student
Register your app by adding the following line under INSTALLED_APPS in Django settings.py file
‘student’,
So, your final INSTALLED_APPS variable should look like this:
INSTALLED_APPS = [
"django.contrib.admin",
"django.contrib.auth",
"django.contrib.contenttypes",
"django.contrib.sessions",
"django.contrib.messages",
"django.contrib.staticfiles",
'student'
]
After that, create a model for the student app to store student objects. For this project, we will have first_name and last_name fields.
class Student(models.Model):
first_name = models.CharField(max_length=255)
last_name = models.CharField(max_length=255)
def __str__(self):
return f"{self.first_name}, {self.last_name}"
Run the migrations to make persistent changes to the database
python manage.py makemigrations
python manage.py migrate
Create a few student objects and store them in the database. Type the following in the Terminal
python manage.py shell
You will get a typical Python prompt with these arrows
>>>
Type the following
Student.objects.create(first_name="Luke", last_name="Skywalker")
Student.objects.create(first_name="Leia", last_name="Organa")
Student.objects.create(first_name="Obi-Wan", last_name="Kenobi")
Alternatively, you may create a superuser account, register your Student model to the admin, and add student objects within the Django admin page.
That’s it. We have a few student objects, at least.
It’s time to retrieve an object using the get() method.
How to get a single object in Django using the .get() method
You can retrieve an object from the database using the Model.objects.get() method. The method is manual because you must specify each object when you want to retrieve it.
Thus, if you have more than one object in your database, you must use the method for each object.
Here’s how to retrieve a single object from the database.
Step 1: Identify the value of a field for the object that you want to retrieve from the database
An example of a field would be an id, name, slug, title, etc.
Note that: you must use a unique value for each object. Otherwise, Django will throw a MultipleObjectsReturned error when a value matches multiple objects containing the same value stored in the database.
A better option is to use the id field, which is unique across all objects.
Step 2: Write your Model.objects.get() method within the views.py file
You need to write the functionality of retrieving the object or objects in your views. That way, you can connect the view to the URL, which the user can use to view the object on a web page.
Open the views.py file of the app containing your database model. Add the following code:
from django.shortcuts import render
# Import the model containing your student object
from .models import Student
def student1(request):
# get a single unique object
student = Student.objects.get(id=1)
# define the template name to display the single item
context = {
'student': student
}
return render(request, template_name='index.html', context=context)
Here, we are importing the Model containing the student objects.
We create a view function that we will use to insert the .get() method code, retrieve an object of id 1, define the reference name for our student object as an object, and render it on an HTML template that we’ll create called index.html.
You can also use other field names to retrieve a single object.
In this case, we can use the first names because they are unique. So, the query should be Student.objects.get(first_name=”Leia”).
Take note: using the last name field to retrieve an object would result in an error because Django encounters multiple objects with the same value.
Two student have the same last name, Skywalker.
Create a new directory called templates inside the student app folder.
Then create a new HTML file called index.html to render our student object to the user upon accessing the URL.
mkdir student/templates
touch student/templates/index.html
Open student/templates/index.html and add the following line of code
{{ student }}
Here, I am using a template variable to display the student object. Remember, we defined the variable inside the dictionary of our view function.
Create urls.py file of the student file
touch student/urls.py
Add the following lines of code to the urls.py file
from django.urls import path
# import the view function to display the student object
from .views import student1
# define all the url endpoints for the student app
urlpatterns = [
path('', student1),
]
Register the new app URLs inside the main Django URL configuration file.
Open the main project urls.py and add the following code. exampleProject/urls.py
from django.contrib import admin
# Add the following line to import include() function
from django.urls import path, include
urlpatterns = [
path("admin/", admin.site.urls),
# register the student app urls here
path('student', include('student.urls')),
]
Save the file and run Django local development server.
python manage.py runserver
Open, 127.0.0.1:8000/student
And voila! You should see the name of the student object with an id of 1
You can change the object’s id to 2, refresh the page, and Django should display the second object.
Note: To retrieve the first object in a Django model, you should not use 0, as it is in the case for Python, where indexing starts at 0. When dealing with a Django database, indexing starts at 1 because SQL stores items starting with an index of 1.
That’s how you use the get() method to retrieve a single object from the database in Django.
However, you should not use this method if you need to have so many items stored in your database.
Let’s see a more intuitive way of retrieving an object from the database using the same get method.
Instead of hard coding the id of each object in the view function, we can supply the id in the URL by changing the view function to look like this:
def student1(request, id):
# get a single unique object using the id provided in the url
student = Student.objects.get(id=id)
# define the template name to display the single item
context = {
'student': student
}
return render(request, template_name='index.html', context=context)
Then change the URL to allow the addition of an id at the end
Access http://127.0.0.1:8000/student and append the id of an object at the end. http://127.0.0.1:8000/student/1 or http://127.0.0.1:8000/student/2 and so on.
That’s an easier way of getting a single object in Django using the get() method.
It forms the basis of learning how to retrieve an object from a Model.
How to get a single unique object in Django using the filter() method
Another way to retrieve a single object in Django is to use the filter method.
As with the get method, it implies that only one object will be retrieved from the database. The filter method gets one or more objects from the database. The item returned from a filter() method is a queryset– a list of the object or objects returned when the query matches an object or multiple objects. The filter method() will return a single object when it encounters a query that matches only one object. However, the filter method can also return, “filter out” more than one object when multiple objects have the same value specified in the query.
Mostly, when using unique values in your filter() method, Django will return one object only. This is common when dealing with ids or primary keys.
How to get a single value from a queryset in Django? To access the values of each object, you must specify its position in the queryset. For a single item, the position of the object will be 1, which can also be called, first().
When multiple objects match the query, the objects following the first object can be accessed the same way as list, queryset[2]. The last item in a Django filter() queryset can be accessed through an additional filter method called last().
So, to get the first object in a Django queryset, here’s the code you would use.
student = Student.objects.filter().first()
To get the second object in a queryset from a filter() method:
student = Student.objects.filter()[2]
To get the last item in a queryset:
student = Student.objects.filter().last()
In this section, we will focus on retrieving only one object using a unique field with the filter method.
Thus, we must filter out only one object with an id that we supply. Thus, if we supply an id of 1, we will get only one object in the queryset because only one object exists in the database with an id of 1.
Note that we get a queryset when we use the filter() method. So, we must use the .first() method to access that same object existing in the queryset.
Here’s what I mean
student = Student.objects.filter(id=id)
The above code returns a queryset containing a single object with an id of 1 if we supply 1 in the URL.
The same happens when we supply an id matching another object, let’s say id = 2.
Notice that we do not get the names of the students. Rather, we’re getting a queryset.
Thus, we must access the position of the object in the queryset list by using the first() method or queryset[0].
So,
student = Student.objects.filter(id=id).first()
OR
student = Student.objects.filter(id=id)[0]
Because we only have one object, you cannot use positions 1 or 2 here. The queryset, the list, contains only one item with an id supplied in the URL.
Django will return an error, IndexError because ideally, we only have one item in the queryset list.
So, to avoid the IndexError, list index out of range error, when retrieving a single item from the database, only use the .first() method or use an index value of 0, qs[0], since the queryset itself is a list.
This code works the same as with the get() method above– retrieve/filter out a single object from the database.
student = Student.objects.filter(id=id).first()
However, the get() and filter() methods is not an effective way to retrieve a single object from the database.
The reason is that you must anticipate the exceptions such as MultipleObjectsReturned and DoesNotExist that arise when dealing with a single object. A better approach is to use a method that does that for you automatically without you having to write the exception handling yourself.
How to get a single object from the database in Django using get_object_or_404 method
The get_object_or_404() method is a more intuitive method for retrieving items from the database.
The method handles the exceptions for you when Django encounters a query for an object that doesn’t exist in the database.
You can use the get_object_or_404 method just the same way you would with the get() method.
But first, you must import the method using the following line of code:
from django.shortcuts import render, get_object_or_404
Then use it when retrieving an object specifying the model and the field that uniquely identifies each object, in this case, the id.
student = get_object_or_404(Student, id=id)
That’s all you need to retrieve a single object in Django using the get_object_or_404 method.
Refresh your Django student page and it should work the same as before.
from django.shortcuts import render, get_object_or_404
# Import the model containing your student object
from .models import Student
# added a new argument to allow supplying of the id in the url
def student1(request, id):
# get a single object using the id provided in the url
student = get_object_or_404(Student, id=id)
# define the template name to display the single item
context = {
'student': student
}
return render(request, template_name='index.html', context=context)
The method works well and will handle the errors for you by displaying a 404 error page to the users. This method works well with function based views.
When dealing with class based views, Django provides better and out-of-the-box functionality for retrieving single objects from the database.
Let’s see how retrieving a single unique object works with class based views.
How to get a single object in Django using class based view DetailView
When working with class based views, Django’s generic DetailView encompasses what get() and filter().first() methods do, allowing you to retrieve a single object from a given Django model.
Therefore, when you use DetailView, you must supply your URL parameter with the primary key, which is associated with the id, that will match a single object.
Besides, you may use a unique slug in your URL parameter to return a more user-friendly URL.
Other things that must be supplied to the Django generic DetailView are:
- A template
- Model to retrieve the object
For our Django project here’s how to retrieve a single student object from the Student model and display it to the user.
First import the generic DetailView and the model to use to retrieve the object
from django.views.generic.detail import DetailView
from .models import Student
Then, define the view using the class keyword- we’re using class based views here.
class StudentDetailView(DetailView):
model = Student
template_name = 'index.html'
So, your final, views.py file should look like this
from django.views.generic.detail import DetailView
# Import the model containing your student object
from .models import Student
class StudentDetailView(DetailView):
model = Student
template_name = 'index.html'
Then define the URL pattern for the single object. Remember, we must supply the primary key or slug to be used to retrieve the object here.
Note: Django generic DetailView does not accept an id URL parameter. DetailView only accepts a primary key value instead of id.
So, your final urls.py should look like this.
from django.urls import path
# import class based view used to display a single object
from .views import StudentDetailView
urlpatterns = [
# unique id student detail view
path('/<int:id>/', StudentDetailView.as_view())
]
Open the browser and supply an id, http://127.0.0.1:8000/student/4/
And voila!
That should work.
Note that Django handles the exceptions for you automatically when you supply an id that does not match any object in the database.
If you supply an id parameter to a URL when using generic DetailView, Django will throw AttributeError at / Generic detail view StudentDetailView must be called with either an object pk or a slug in the URLconf.
To resolve the error, replace the id parameter with an object primary key (pk) or a slug.
Here’s an example:
Using a primary key
path('/<int:pk>/', StudentDetailView.as_view())
Or, use a slug
path('/<slug:slug>/', StudentDetailView.as_view())
When using a slug, make sure you have such a slug field defined in your Model.
And that’s how you retrieve a single object from the database in Django when using DetailView.
Related Questions
Which is the best approach to get a single object from the database in Django?
When dealing with function based views, you should use the get_object_or_404 method to mitigate the errors of retrieving an object that does not exist. With class based views, you should use the DetailView to retrieve a single object from the database.
What is first() in Django?
The .first() method is used in a filter() method to get the first object in a queryset. If the queryset is empty, especially when you do not have items in your database, first() method returns None. A queryset is generated when dealing with the filter() method to retrieve objects.
Here is an example using the .first() method: Student.objects.filter(age=20).first(). The first method takes the following syntax Model.objects.filter().first().
Conclusion
Retrieving objects from the database and displaying them on your web pages in Django is a very straightforward process.
Django provides a couple of methods to work with when using function based views. These methods include the get(), filter(), and get_bject_or_404() methods.
Besides, if you want an out-of-the-box functionality, you may opt to use class based views further reducing the amount of code that you have to write and improving performance. In class based views, you can use the generic DetailView to retrieve single objects from the database in Django.
Out of these methods used for retrieving a single object, the best and most efficient method to use in a function based view is the get_object_or_404 method. It handles the errors that arise from retrieving a single object from your models.
For class based views, you have the generic DetailView to get a single object by using a primary key or a slug to uniquely identify each object.
And that’s it for this tutorial.
See ya!