Best practice for intercepting error responses in Django and DRF

I have a Django app that uses the Django Rest Framework. Errors may occur on the Django side, like integrity errors in the database. The default error response will be something like:

  "details": {
    "email": "user with this email already exists."

Validation errors may also occur DRF side:

  "detail": ...

As you can see, there is an inconsistency in the response message, as Django uses “details” and DRF uses “detail”.

However, I like neither format. I want to respond with a message in the following format:

  "message": ...
  "code": ...

My question is:

What is the best practice to handle both Django and DRF exceptions and respond with a custom response body?

I have tried:

  1. custom exception handler in DRF, but this only handles DRF exceptions
  2. custom error messages when defining models
      email = models.EmailField(error_messages={"required": {"message": "", "code": 123}})
    but Django can’t handle a dictionary as a message
  3. Adding a DRF validator to my serializer:
    email = serializers.EmailField(
                    "message": "a user with this email already exists",
                    "code": status.EMAIL_EXISTS,
    but this does not override the response body, but instead it embeds the message as an error message to the {"details": {"message": {<embedded dictionary>}}}

The only thing I believe would work, is to try-except all exceptions inside my Views, but I would like to know if there is a prettier way than placing all my View code inside a try block.