Skip to content
GitLab
Projects Groups Topics Snippets
  • /
  • Help
    • Help
    • Support
    • Community forum
    • Submit feedback
    • Contribute to GitLab
  • Sign in
  • Django Template Django Template
  • Project information
    • Project information
    • Activity
    • Labels
    • Members
  • Repository
    • Repository
    • Files
    • Commits
    • Branches
    • Tags
    • Contributor statistics
    • Graph
    • Compare revisions
  • Issues 11
    • Issues 11
    • List
    • Boards
    • Service Desk
    • Milestones
  • Merge requests 1
    • Merge requests 1
  • CI/CD
    • CI/CD
    • Pipelines
    • Jobs
    • Schedules
  • Deployments
    • Deployments
    • Environments
    • Releases
  • Monitor
    • Monitor
    • Incidents
  • Analytics
    • Analytics
    • Value stream
    • CI/CD
    • Repository
  • Wiki
    • Wiki
  • Activity
  • Graph
  • Create a new issue
  • Jobs
  • Commits
  • Issue Boards
Collapse sidebar
  • IzeniIzeni
  • Django TemplateDjango Template
  • Wiki
  • exception handling tips

exception handling tips · Changes

Page history
Update exception handling tips authored Oct 31, 2024 by Jordan Price's avatar Jordan Price
Show whitespace changes
Inline Side-by-side
exception-handling-tips.md
View page @ 363fba51
...@@ -6,12 +6,69 @@ Before continuing, please read the [Exceptions](https://www.django-rest-framewor ...@@ -6,12 +6,69 @@ Before continuing, please read the [Exceptions](https://www.django-rest-framewor
The only exceptions handled by DRF's exception handler are subclasses of `rest_framework.exceptions.APIException`, which means that when explicitly raising an exception in a serializer or view, it MUST be a subclass of `APIException`. If any other type of exception is raised it will not be handled by the DRF exception handler, and will instead result in a Django error page (when DEBUG is true). The only exceptions handled by DRF's exception handler are subclasses of `rest_framework.exceptions.APIException`, which means that when explicitly raising an exception in a serializer or view, it MUST be a subclass of `APIException`. If any other type of exception is raised it will not be handled by the DRF exception handler, and will instead result in a Django error page (when DEBUG is true).
These are the subclasses of `APIException` provided by Django REST Framework. You can also create your own subclasses of `APIException` if needed. The implementation for these exceptions can be [found here](https://github.com/encode/django-rest-framework/blob/master/rest_framework/exceptions.py) These are the subclasses of `APIException` provided by Django REST Framework. You can also create your own subclasses of `APIException` if needed. The implementation for these exceptions can be [found here](https://github.com/encode/django-rest-framework/blob/master/rest_framework/exceptions.py).
`APIException`, `ValidationError`, `ParseError`, `AuthenticationFailed`, `NotAuthenticated`, `PermissionDenied`, `NotFound`, `MethodNotAllowed`, `NotAcceptable`, `UnsupportedMediaType`, `Throttled` `APIException`, `ValidationError`, `ParseError`, `AuthenticationFailed`, `NotAuthenticated`, `PermissionDenied`, `NotFound`, `MethodNotAllowed`, `NotAcceptable`, `UnsupportedMediaType`, `Throttled`
### Special case of PermissionDenied and Http404
### Non DRF exceptions ### Non DRF exceptions
Since DRF can only handle the above exceptions, we must catch and convert any other type of exception that could be raised. Here's a common example:
```python
user = EmailUser.objects.get(pk=1234)
```
If a `EmailUser` with the id `1234` does not exist an exception that is a subclass of `django.core.exceptions.ObjectDoesNotExist` will be raised. As the exception is not a subclass of `rest_framework.exceptions.APIException`, the error will not be handled by DRF's exception handler and we'll instead see something like this.
![image](uploads/fc01826cea474525992becc3936bcff4/image.png)
To properly handle this error, we must explicitly catch it and return a corresponding error that DRF can handle.
```python
from rest_framework import exceptions
try:
user = EmailUser.objects.get(pk=1234)
except EmailUser.DoesNotExist:
raise exceptions.NotFound("User not found")
```
Now we'll get a proper error message that the frontend can use!
![image](uploads/36aa71266bd755656f06de6b5907a74a/image.png)
### Special case of PermissionDenied and Http404
The *only* exceptions to this rule are `django.core.exceptions.PermissionDenied` and `django.http.Http404`, which DRF's exception handler specifically converts to `rest_framework.exceptions.PermissionDenied` and `rest_framework.exceptions.NotFound` ([implementation](https://github.com/encode/django-rest-framework/blob/master/rest_framework/views.py#L82))
### Similarly named exceptions
There are some DRF exception names that overlap exceptions from Django or Python builtin's. For example `ValidationError`, `PermissionDenied` etc. Make sure you know which type of exception you're raising and be sure that it's the one from DRF! What can help is if you need to use Django's `ValidationError` or `PermissionDenied` error, import them with an alias so that you can handle them and conver them to the right DRF type:
```python
from django.core.exceptions import ValidationError as DjangoValidationError
from rest_framework import exceptions
try:
django_validate_password(password)
except DjangoValidationError as error:
raise exceptions.ValidationError(error.messages)
```
## Always raise an exception, never manually return a `Response` with an error status code ## Always raise an exception, never manually return a `Response` with an error status code
It may be tempting sometimes to return a `rest_framework.respose.Response` instead of raising an exception:
```python
return Response("Something went wrong", status=status.HTTP_400_BAD_REQUEST)
```
This will appear to work fine, and the frontend *may* even be able to handle it properly, but only if the response body matches a format that the frontend expects when it encounters `APIException` errors. In any case, it's always better to raise an exception!
## `ValidationError` must only be raised in the `validate` or `validate_<field>` methods of a serializer ## `ValidationError` must only be raised in the `validate` or `validate_<field>` methods of a serializer
## Messages will be displayed to the user!
\ No newline at end of file This one definitely took me the most time to realize, and it isn't necessarily a rule, but it makes a huge difference when handling errors from a frontend.
DRF's `ValidationError` is handled differently than the rest of the `APIException` subclasses. Rather than having a `detail: str` message body, it'll return a dict of errors related to either specific fields, or `non_field_errors` if not related to any specific field.
## Assume messages will be displayed to the user!
\ No newline at end of file
Clone repository
  • exception handling tips
  • recommended development tools
  • stripe integration