Django Web Framework[Part-8]
Error Handling in Django
An application will contain errors in some form no matter how much its tested and Quality Assurance has performed.
It’s not only incorrect code, sometimes network is also not reliable. Let’s explore error handling in Django.
Http status codes:
We configure error handling view in Django.
These error handling views is applied to a separate views.py file which can be used across the project.
Handling Errors in Views
The response from the view is an object of HttpResponse. Its contents are also associated with a respective status code.
from django.http import HttpResponse, HttpResponseNotFound
def my_view(request):
# ...
if condition==True:
return HttpResponseNotFound('<h1>Page not found</h1>')
else:
return HttpResponse('<h1>Page was found</h1>')
Status code 404 implies that the resource requested by the client cannot be found. Django has a generic HttpResponseNotFound class. You can return its object to convey the appropriate message.
from django.http import HttpResponse
def my_view(request):
# ...
if condition==True:
return HttpResponse('<h1>Page not found</h1>', status_code='404')
else:
return HttpResponse('<h1>Page was found</h1>')
The main difference in using HttpResponseNotFound as opposed to HttpResponse that must be understood is that Django internally sends an error code 404. The appropriate page for 404 can then be configured and rendered, else the browser displays its default 404 view.
A common cause of the 404 status code is the user entering an incorrect URL.
Django makes it easy to work with this error code.
Put a string argument inside the HttpResponseNotFound() to view the error message. Instead, raise Http404. Django displays a standard error page with the status.
(Instead, raise Http404 exception).
Scenario to handle exception
You have a Product model in the app. The user wants the details of a product with a specific Product ID. In the following view function, id is the parameter obtained from the URL. It tries to determine whether any product with the given id is available. If not, the Http404 exception is raised.
from django.http import Http404, HttpResponse
from .models import Product
def detail(request, id):
try:
p = Product.objects.get(pk=id)
except Product.DoesNotExist:
raise Http404("Product does not exist")
return HttpResponse("Product Found")
Just like the HttpResponseNotFound, there are a number of other predefined classes such as HttpResponseBadRequest, HttpResponseForbidden and so on.
Custom error pages
If you want to show your own error page whenever the user encounters a 404 error, you must create a 404.html page and put it in the project/templates folder.
You will learn more about how to do this later when you explore templates.
Displaying error messages in the browser
Usually, the Django development server is in DEBUG mode, which shows the error’s traceback instead of the exception.
To render the custom exception message, the DEBUG variable in the project’s settings should be set to False.
#settings.py
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG=FALSE
Exception classes
Django’s exception classes are defined in the django.core.exceptions module.
Some important exception types are:
- ObjectDoesNotExist: All the exceptions of the DoesNotExist are inherited from this base exception.
- EmptyResultSet: This exception is raised if a query does not return any result.
- FieldDoesNotExist: This exception is raised when the requested field does not exist.
try:
field = model._meta.get_field(field_name)
except FieldDoesNotExist:
return HttpResponse("Field Does not exist")
- MultipleObjectsReturned: When you expect a certain query to return only a single object, however multiple objects are returned. This is when you need to raise this exception.
- PermissionDenied: This exception is raised when a user does not have permission to perform the action requested.
def myview(request):
if not request.user.has_perm('myapp.view_mymodel'):
raise PermissionDenied()
return HttpResponse()
- ViewDoesNotExist: This exception is raised by django.urls when a requested view does not exist, possibly because of incorrect mapping defined in the URLconf.
When a certain view is called with a POST or PUT request, the request body is populated by the form data.
Django’s Form API defines various fields specific to the type of data stored. For example, you have EmailField, FileField, IntegerField, MultipleChoiceField.
These fields have built-in validators. The is_valid() method returns True if the validations are passed. You can raise an exception if it returns False.
def myview(request):
if request.method == "POST":
form = MyForm(request.POST)
if form.is_valid():
#process the form data
else:
return HttpResponse("Form submitted with invalid data")
Class based Views
In function based view, the framework passed HTTP request to the function and expecting the HTTP response back. While this works for some use cases, developers often find the need of more robust solution to implement complex logic in view. Django provides class based view approach to resolve this.
Class based views allow you to use views as objects and offer an alternative to function based views.Remember that a view is callable in that it can take a request and return a response. This process works great for the HTTP protocol.
When dealing with HTTP, you use specific methods for the different types of requests. Such as get, post, put and delete and these are the core CRUD operations for any web page. If you use a function based view, you need to perform some conditional logic on the request method, like an if else statement. But class based views, uses a different approach than function based views. Instead of using conditional branching, such as if else statements, Class based views respond to HTTP requests using class instance methods.
Instance methods are default python methods, defined in classes that can access objects or instances of a class. In a class based view, this can be simplified by adding different instance methods for the get and post requests. And these methods will implement the view logic independently.
Class based views, respond with different class instance methods to HTTP requests in place of writing conditional branches, such as using if else, statements inside the same function. The advantage of using a class based view in this scenario, is that it allows you to remove the conditional logic to check the incoming request for the type of method.
This simplifies the code and separates the logic, making it easy to understand.
Another helpful aspect is the ability to have object oriented techniques, such as mixins or multiple inheritance, which factor code into reusable components.
In Django, you can extend the functionality of class based views using mixins. Mixins are class based generic views that are flexible compared to their function based view equivalent. It can help to think of a mixin as a form of multiple inheritance, recall that inheritance as one of the core concepts of object oriented design or OOP.
It allows you to derive one class from another for a hierarchy of classes with similar attributes.
For example, suppose you have a class called food. Other classes that can inherit from this class could be appetizers, entree and desserts. They are all types of food and would share a lot of common attributes. Some common mixins developers use are create, list, retrieve, update and delete.
Let’s explore these briefly now.
Use create to create a model instance. Use list to list a query set. Use retrieve to retrieve a model instance. Use update to update a model instance and use delete to delete a model instance. It’s important to note that when using mixins, they can’t be all used together. And in some cases it can make your code harder to read.
So, it’s best to use them wisely.
Additional resources
Here is a list of additional resources that may be helpful as you continue your learning journey.
The django.urls functions for use in URLconfs — official documentation
Render HTML Forms — GET and POST in Django
Link to my Repo
🎯 https://github.com/Debapriya-dev/BackendDevelopment
Additional resources
Creating views– official documentation
The render() function in Django
Getting query parameters from a request in Django
What’s Next
Previous topics ⭐️👇
Next topics ⭐️👇
🎯Django Web Framework[Part-9][Upcoming..]
I will sum up few more topics which I found interesting to look at. Let’s get learning🍀!
🙏 Thank you for reading to the end! Comment below or email me at dbpr.sinha@gmail.com if you have any questions. For more articles please stay tuned. Also follow my links.