Error handling

django-modern-rest has 3 layers where errors might be handled. It provides flexible error handling logic on Endpoint, Controller, and global levels.

All error handling functions always accept 3 arguments:

  1. Endpoint where error happened

  2. Controller where error happened

  3. Exception that happened

Here’s how it works:

  1. We first try to call error_handler that was passed into the endpoint definition via modify() or validate()

  2. If it returns django.http.HttpResponse, return it to the user

  3. If it raises, call handle_error() for sync controllers and handle_async_error() for async controllers

  4. If controller’s handler returns HttpResponse, return it to the user

  5. If it raises, call configured global error handler, by default it is global_error_handler() (it is always sync)

Warning

There are two things to keep in mind:

  1. Async endpoints will require async error_handler parameter, Sync endpoints will require sync error_handler parameter. This is validated on endpoint creation

  2. We don’t allow to define sync handle_error handlers for async controllers. We also don’t allow async handle_async_error handlers for sync controllers.

Note

APIError does not follow any of these rules and has a default handler, which will convert an instance of APIError to HttpResponse via to_error() call.

You don’t need to catch APIError in any way, unless you know what you are doing.

Customizing endpoint error handler

Let’s pass custom error handling to a single endpoint:

Run result

$ curl http://127.0.0.1:8000/api/math/ -D - -X PATCH -d '{"left": 1, "right": 0}' -H 'Content-Type: application/json'
HTTP/1.1 400 Bad Request
date: Tue, 14 Apr 2026 17:08:27 GMT
server: uvicorn
Content-Type: application/json
X-Frame-Options: DENY
Vary: Accept-Language
Content-Language: en
Content-Length: 39
X-Content-Type-Options: nosniff
Referrer-Policy: same-origin
Cross-Origin-Opener-Policy: same-origin

{"detail":[{"msg":"division by zero"}]}

$ curl http://127.0.0.1:8000/api/math/ -D - -X POST -d '{"left": 1, "right": 0}' -H 'Content-Type: application/json'
HTTP/1.1 500 Internal Server Error
date: Tue, 14 Apr 2026 17:08:27 GMT
server: uvicorn
Content-Type: text/html; charset=utf-8
X-Frame-Options: DENY
Vary: Accept-Language, Cookie
Content-Language: en
Content-Length: 92520
X-Content-Type-Options: nosniff
Referrer-Policy: same-origin
Cross-Origin-Opener-Policy: same-origin

<!DOCTYPE html>
<html lang="en">
<head>
  <meta http-equiv="content-type" content="text/html; charset=utf-8">
  <meta name="robots" content="NONE,NOARCHIVE">
  <title>ZeroDivisionError
          at /api/math/</title>
  <style>
    html * { padding:0; margin:0; }
    body * { padding:10px 20px; }
    body * * { padding:0; }
    body { font-family: sans-serif; background-color:#fff; color:#000; }
    body > :where(header, main, footer) { border-bottom:1px solid #ddd; }
    h1 { font-weight:normal; }
    h2 { margin-bottom:.8em; }
    h3 { margin:1em 0 .5em 0; }
    h4 { margin:0 0 .5em 0; font-weight: normal; }
    code, pre { font-size: 100%; white-space: pre-wrap; word-break: break-word; }
    summary { cursor: pointer; }
    table { border:1px solid #ccc; border-collapse: collapse; width:100%; background:white; }
    tbody td, tbody th { vertical-align:top; padding:2px 3px; }
    thead th {
      padding:1px 6px 1px 3px; background:#fefefe; text-align:left;
      font-weight:normal; font-size: 0.6875rem; border:1px solid #ddd;
    }
    tbody th { width:12em; text-align:right; color:#666; padding-right:.5em; }
    table.vars { margin:5px 10px 2px 40px; width: auto; }
    table.vars td, table.req td { font-family:monospace; }
    table td.code { width:100%; }
    table td.code pre { overflow:hidden; }
    table.source th { color:#666; }
    table.source td { font-family:monospace; white-space:pre; border-bottom:1px solid #eee; }
    ul.traceback { list-style-type:none; color: #222; }
    ul.traceback li.cause { word-break: break-word; }
    ul.traceback li.frame { padding-bottom:1em; color:#4f4f4f; }
    ul.traceback li.user { background-color:#e0e0e0; color:#000 }
    div.context { padding:10px 0; overflow:hidden; }
    div.context ol { padding-left:30px; margin:0 10px; list-style-position: inside; }
    div.context ol li { font-family:monospace; white-space:pre; color:#777; cursor:pointer; padding-left: 2px; }
    div.context ol li pre { display:inline; }
    div.context ol.context-line li { color:#464646; background-color:#dfdfdf; padding: 3px 2px; }
    div.context ol.context-line li span { position:absolute; right:32px; }
    .user div.context ol.context-line li { background-color:#bbb; color:#000; }
    .user div.context ol li { color:#666; }
    div.commands, summary.commands { margin-left: 40px; }
    div.commands a, summary.commands { color:#555; text-decoration:none; }
    .user div.commands a { color: black; }
    #summary { background: #ffc; }
    #summary h2 { font-weight: normal; color: #666; }
    #info { padding: 0; }
    #info > * { padding:10px 20px; }
    #explanation { background:#eee; }
    #template, #template-not-exist { background:#f6f6f6; }
    #template-not-exist ul { margin: 0 0 10px 20px; }
    #template-not-exist .postmortem-section { margin-bottom: 3px; }
    #unicode-hint { background:#eee; }
    #traceback { background:#eee; }
    #requestinfo { background:#f6f6f6; padding-left:120px; }
    #summary table { border:none; background:transparent; }
    #requestinfo h2, #requestinfo h3 { position:relative; margin-left:-100px; }
    #requestinfo h3 { margin-bottom:-1em; }
    .error { background: #ffc; }
    .specific { color:#cc3300; font-weight:bold; }
    h2 span.commands { font-size: 0.7rem; font-weight:normal; }
    span.commands a:link {color:#5E5694;}
    pre.exception_value { font-family: sans-serif; color: #575757; font-size: 1.5rem; margin: 10px 0 10px 0; }
    .append-bottom { margin-bottom: 10px; }
    .fname { user-select: all; }
  </style>
  
  <script>
    function hideAll(elems) {
      for (var e = 0; e < elems.length; e++) {
        elems[e].style.display = 'none';
      }
    }
    window.onload = function() {
      hideAll(document.querySelectorAll('ol.pre-context'));
      hideAll(document.querySelectorAll('ol.post-context'));
      hideAll(document.querySelectorAll('div.pastebin'));
    }
    function toggle() {
      for (var i = 0; i < arguments.length; i++) {
        var e = document.getElementById(arguments[i]);
        if (e) {
          e.style.display = e.style.display == 'none' ? 'block': 'none';
        }
      }
      return false;
    }
    function switchPastebinFriendly(link) {
      s1 = "Switch to copy-and-paste view";
      s2 = "Switch back to interactive view";
      link.textContent = link.textContent.trim() == s1 ? s2: s1;
      toggle('browserTraceback', 'pastebinTraceback');
      return false;
    }
  </script>
  
</head>
<body>
<header id="summary">
  <h1>ZeroDivisionError
       at /api/math/</h1>
  <pre class="exception_value">division by zero</pre>
  <table class="meta">

    <tr>
      <th scope="row">Request Method:</th>
      <td>POST</td>
    </tr>
    <tr>
      <th scope="row">Request URL:</th>
      <td>http://127.0.0.1:45355/api/math/</td>
    </tr>

    <tr>
      <th scope="row">Django Version:</th>
      <td>5.2.13</td>
    </tr>

    <tr>
      <th scope="row">Exception Type:</th>
      <td>ZeroDivisionError</td>
    </tr>


    <tr>
      <th scope="row">Exception Value:</th>
      <td><pre>division by zero</pre></td>
    </tr>


    <tr>
      <th scope="row">Exception Location:</th>
      <td><span class="fname">/home/docs/checkouts/readthedocs.org/user_builds/django-modern-rest/checkouts/0.7.0/docs/examples/error_handling/endpoint.py</span>, line 45, in post</td>
    </tr>


    <tr>
      <th scope="row">Raised during:</th>
      <td>examples.error_handling.endpoint.MathController</td>
    </tr>

    <tr>
      <th scope="row">Python Executable:</th>
      <td>/home/docs/checkouts/readthedocs.org/user_builds/django-modern-rest/envs/0.7.0/bin/python</td>
    </tr>
    <tr>
      <th scope="row">Python Version:</th>
      <td>3.12.10</td>
    </tr>
    <tr>
      <th scope="row">Python Path:</th>
      <td><pre><code>[&#x27;/home/docs/checkouts/readthedocs.org/user_builds/django-modern-rest/checkouts/0.7.0&#x27;,
 &#x27;/home/docs/checkouts/readthedocs.org/user_builds/django-modern-rest/checkouts/0.7.0/django_test_app&#x27;,
 &#x27;/home/docs/checkouts/readthedocs.org/user_builds/django-modern-rest/checkouts/0.7.0/docs&#x27;,
 &#x27;/home/docs/.asdf/installs/python/3.12.10/lib/python312.zip&#x27;,
 &#x27;/home/docs/.asdf/installs/python/3.12.10/lib/python3.12&#x27;,
 &#x27;/home/docs/.asdf/installs/python/3.12.10/lib/python3.12/lib-dynload&#x27;,
 &#x27;/home/docs/checkouts/readthedocs.org/user_builds/django-modern-rest/envs/0.7.0/lib/python3.12/site-packages&#x27;]</code></pre></td>
    </tr>
    <tr>
      <th scope="row">Server time:</th>
      <td>Tue, 14 Apr 2026 12:08:27 -0500</td>
    </tr>
  </table>
</header>

<main id="info">




<div id="traceback">
  <h2>Traceback <span class="commands"><a href="#" role="button" onclick="return switchPastebinFriendly(this);">
    Switch to copy-and-paste view</a></span>
  </h2>
  <div id="browserTraceback">
    <ul class="traceback">
      
        
        <li class="frame django">
          
            <code class="fname">/home/docs/checkouts/readthedocs.org/user_builds/django-modern-rest/envs/0.7.0/lib/python3.12/site-packages/django/core/handlers/exception.py</code>, line 42, in inner
          

          
            <div class="context" id="c140501914946432">
              
                <ol start="35" class="pre-context" id="pre140501914946432">
                
                  <li onclick="toggle('pre140501914946432', 'post140501914946432')"><pre>    can rely on getting a response instead of an exception.</pre></li>
                
                  <li onclick="toggle('pre140501914946432', 'post140501914946432')"><pre>    &quot;&quot;&quot;</pre></li>
                
                  <li onclick="toggle('pre140501914946432', 'post140501914946432')"><pre>    if iscoroutinefunction(get_response):</pre></li>
                
                  <li onclick="toggle('pre140501914946432', 'post140501914946432')"><pre></pre></li>
                
                  <li onclick="toggle('pre140501914946432', 'post140501914946432')"><pre>        @wraps(get_response)</pre></li>
                
                  <li onclick="toggle('pre140501914946432', 'post140501914946432')"><pre>        async def inner(request):</pre></li>
                
                  <li onclick="toggle('pre140501914946432', 'post140501914946432')"><pre>            try:</pre></li>
                
                </ol>
              
              <ol start="42" class="context-line">
                <li onclick="toggle('pre140501914946432', 'post140501914946432')"><pre>                response = await get_response(request)
                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^</pre> <span>…</span></li>
              </ol>
              
                <ol start='43' class="post-context" id="post140501914946432">
                  
                  <li onclick="toggle('pre140501914946432', 'post140501914946432')"><pre>            except Exception as exc:</pre></li>
                  
                  <li onclick="toggle('pre140501914946432', 'post140501914946432')"><pre>                response = await sync_to_async(</pre></li>
                  
                  <li onclick="toggle('pre140501914946432', 'post140501914946432')"><pre>                    response_for_exception, thread_sensitive=False</pre></li>
                  
                  <li onclick="toggle('pre140501914946432', 'post140501914946432')"><pre>                )(request, exc)</pre></li>
                  
                  <li onclick="toggle('pre140501914946432', 'post140501914946432')"><pre>            return response</pre></li>
                  
                  <li onclick="toggle('pre140501914946432', 'post140501914946432')"><pre></pre></li>
                  
              </ol>
              
            </div>
          

          
            
              <details>
                <summary class="commands">Local vars</summary>
            
            <table class="vars" id="v140501914946432">
              <thead>
                <tr>
                  <th scope="col">Variable</th>
                  <th scope="col">Value</th>
                </tr>
              </thead>
              <tbody>
                
                  <tr>
                    <td>exc</td>
                    <td class="code"><pre>ZeroDivisionError(&#x27;division by zero&#x27;)</pre></td>
                  </tr>
                
                  <tr>
                    <td>get_response</td>
                    <td class="code"><pre>&lt;bound method BaseHandler._get_response_async of &lt;django.core.handlers.asgi.ASGIHandler object at 0x7fc926e301d0&gt;&gt;</pre></td>
                  </tr>
                
                  <tr>
                    <td>request</td>
                    <td class="code"><pre>&lt;ASGIRequest: POST &#x27;/api/math/&#x27;&gt;</pre></td>
                  </tr>
                
              </tbody>
            </table>
            </details>
          
        </li>
      
        
        <li class="frame django">
          
            <code class="fname">/home/docs/checkouts/readthedocs.org/user_builds/django-modern-rest/envs/0.7.0/lib/python3.12/site-packages/django/core/handlers/base.py</code>, line 253, in _get_response_async
          

          
            <div class="context" id="c140501914945984">
              
                <ol start="246" class="pre-context" id="pre140501914945984">
                
                  <li onclick="toggle('pre140501914945984', 'post140501914945984')"><pre>            wrapped_callback = self.make_view_atomic(callback)</pre></li>
                
                  <li onclick="toggle('pre140501914945984', 'post140501914945984')"><pre>            # If it is a synchronous view, run it in a subthread</pre></li>
                
                  <li onclick="toggle('pre140501914945984', 'post140501914945984')"><pre>            if not iscoroutinefunction(wrapped_callback):</pre></li>
                
                  <li onclick="toggle('pre140501914945984', 'post140501914945984')"><pre>                wrapped_callback = sync_to_async(</pre></li>
                
                  <li onclick="toggle('pre140501914945984', 'post140501914945984')"><pre>                    wrapped_callback, thread_sensitive=True</pre></li>
                
                  <li onclick="toggle('pre140501914945984', 'post140501914945984')"><pre>                )</pre></li>
                
                  <li onclick="toggle('pre140501914945984', 'post140501914945984')"><pre>            try:</pre></li>
                
                </ol>
              
              <ol start="253" class="context-line">
                <li onclick="toggle('pre140501914945984', 'post140501914945984')"><pre>                response = await wrapped_callback(
                                </pre> <span>…</span></li>
              </ol>
              
                <ol start='254' class="post-context" id="post140501914945984">
                  
                  <li onclick="toggle('pre140501914945984', 'post140501914945984')"><pre>                    request, *callback_args, **callback_kwargs</pre></li>
                  
                  <li onclick="toggle('pre140501914945984', 'post140501914945984')"><pre>                )</pre></li>
                  
                  <li onclick="toggle('pre140501914945984', 'post140501914945984')"><pre>            except Exception as e:</pre></li>
                  
                  <li onclick="toggle('pre140501914945984', 'post140501914945984')"><pre>                response = await sync_to_async(</pre></li>
                  
                  <li onclick="toggle('pre140501914945984', 'post140501914945984')"><pre>                    self.process_exception_by_middleware,</pre></li>
                  
                  <li onclick="toggle('pre140501914945984', 'post140501914945984')"><pre>                    thread_sensitive=True,</pre></li>
                  
              </ol>
              
            </div>
          

          
            
              <details>
                <summary class="commands">Local vars</summary>
            
            <table class="vars" id="v140501914945984">
              <thead>
                <tr>
                  <th scope="col">Variable</th>
                  <th scope="col">Value</th>
                </tr>
              </thead>
              <tbody>
                
                  <tr>
                    <td>callback</td>
                    <td class="code"><pre>&lt;function View.as_view.&lt;locals&gt;.view at 0x7fc926dd8720&gt;</pre></td>
                  </tr>
                
                  <tr>
                    <td>callback_args</td>
                    <td class="code"><pre>()</pre></td>
                  </tr>
                
                  <tr>
                    <td>callback_kwargs</td>
                    <td class="code"><pre>{}</pre></td>
                  </tr>
                
                  <tr>
                    <td>middleware_method</td>
                    <td class="code"><pre>&lt;asgiref.sync.SyncToAsync object at 0x7fc926e6e5d0&gt;</pre></td>
                  </tr>
                
                  <tr>
                    <td>request</td>
                    <td class="code"><pre>&lt;ASGIRequest: POST &#x27;/api/math/&#x27;&gt;</pre></td>
                  </tr>
                
                  <tr>
                    <td>response</td>
                    <td class="code"><pre>None</pre></td>
                  </tr>
                
                  <tr>
                    <td>self</td>
                    <td class="code"><pre>&lt;django.core.handlers.asgi.ASGIHandler object at 0x7fc926e301d0&gt;</pre></td>
                  </tr>
                
                  <tr>
                    <td>wrapped_callback</td>
                    <td class="code"><pre>&lt;asgiref.sync.SyncToAsync object at 0x7fc926eb9850&gt;</pre></td>
                  </tr>
                
              </tbody>
            </table>
            </details>
          
        </li>
      
        
        <li class="frame user">
          
            <code class="fname">/home/docs/.asdf/installs/python/3.12.10/lib/python3.12/concurrent/futures/thread.py</code>, line 59, in run
          

          
            <div class="context" id="c140501914945728">
              
                <ol start="52" class="pre-context" id="pre140501914945728">
                
                  <li onclick="toggle('pre140501914945728', 'post140501914945728')"><pre>        self.kwargs = kwargs</pre></li>
                
                  <li onclick="toggle('pre140501914945728', 'post140501914945728')"><pre></pre></li>
                
                  <li onclick="toggle('pre140501914945728', 'post140501914945728')"><pre>    def run(self):</pre></li>
                
                  <li onclick="toggle('pre140501914945728', 'post140501914945728')"><pre>        if not self.future.set_running_or_notify_cancel():</pre></li>
                
                  <li onclick="toggle('pre140501914945728', 'post140501914945728')"><pre>            return</pre></li>
                
                  <li onclick="toggle('pre140501914945728', 'post140501914945728')"><pre></pre></li>
                
                  <li onclick="toggle('pre140501914945728', 'post140501914945728')"><pre>        try:</pre></li>
                
                </ol>
              
              <ol start="59" class="context-line">
                <li onclick="toggle('pre140501914945728', 'post140501914945728')"><pre>            result = self.fn(*self.args, **self.kwargs)
                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^</pre> <span>…</span></li>
              </ol>
              
                <ol start='60' class="post-context" id="post140501914945728">
                  
                  <li onclick="toggle('pre140501914945728', 'post140501914945728')"><pre>        except BaseException as exc:</pre></li>
                  
                  <li onclick="toggle('pre140501914945728', 'post140501914945728')"><pre>            self.future.set_exception(exc)</pre></li>
                  
                  <li onclick="toggle('pre140501914945728', 'post140501914945728')"><pre>            # Break a reference cycle with the exception &#x27;exc&#x27;</pre></li>
                  
                  <li onclick="toggle('pre140501914945728', 'post140501914945728')"><pre>            self = None</pre></li>
                  
                  <li onclick="toggle('pre140501914945728', 'post140501914945728')"><pre>        else:</pre></li>
                  
                  <li onclick="toggle('pre140501914945728', 'post140501914945728')"><pre>            self.future.set_result(result)</pre></li>
                  
              </ol>
              
            </div>
          

          
            
              <details>
                <summary class="commands">Local vars</summary>
            
            <table class="vars" id="v140501914945728">
              <thead>
                <tr>
                  <th scope="col">Variable</th>
                  <th scope="col">Value</th>
                </tr>
              </thead>
              <tbody>
                
                  <tr>
                    <td>self</td>
                    <td class="code"><pre>None</pre></td>
                  </tr>
                
              </tbody>
            </table>
            </details>
          
        </li>
      
        
        <li class="frame django">
          
            <code class="fname">/home/docs/checkouts/readthedocs.org/user_builds/django-modern-rest/envs/0.7.0/lib/python3.12/site-packages/django/views/decorators/csrf.py</code>, line 65, in _view_wrapper
          

          
            <div class="context" id="c140501914945792">
              
                <ol start="58" class="pre-context" id="pre140501914945792">
                
                  <li onclick="toggle('pre140501914945792', 'post140501914945792')"><pre></pre></li>
                
                  <li onclick="toggle('pre140501914945792', 'post140501914945792')"><pre>        async def _view_wrapper(request, *args, **kwargs):</pre></li>
                
                  <li onclick="toggle('pre140501914945792', 'post140501914945792')"><pre>            return await view_func(request, *args, **kwargs)</pre></li>
                
                  <li onclick="toggle('pre140501914945792', 'post140501914945792')"><pre></pre></li>
                
                  <li onclick="toggle('pre140501914945792', 'post140501914945792')"><pre>    else:</pre></li>
                
                  <li onclick="toggle('pre140501914945792', 'post140501914945792')"><pre></pre></li>
                
                  <li onclick="toggle('pre140501914945792', 'post140501914945792')"><pre>        def _view_wrapper(request, *args, **kwargs):</pre></li>
                
                </ol>
              
              <ol start="65" class="context-line">
                <li onclick="toggle('pre140501914945792', 'post140501914945792')"><pre>            return view_func(request, *args, **kwargs)
                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^</pre> <span>…</span></li>
              </ol>
              
                <ol start='66' class="post-context" id="post140501914945792">
                  
                  <li onclick="toggle('pre140501914945792', 'post140501914945792')"><pre></pre></li>
                  
                  <li onclick="toggle('pre140501914945792', 'post140501914945792')"><pre>    _view_wrapper.csrf_exempt = True</pre></li>
                  
                  <li onclick="toggle('pre140501914945792', 'post140501914945792')"><pre></pre></li>
                  
                  <li onclick="toggle('pre140501914945792', 'post140501914945792')"><pre>    return wraps(view_func)(_view_wrapper)</pre></li>
                  
              </ol>
              
            </div>
          

          
            
              <details>
                <summary class="commands">Local vars</summary>
            
            <table class="vars" id="v140501914945792">
              <thead>
                <tr>
                  <th scope="col">Variable</th>
                  <th scope="col">Value</th>
                </tr>
              </thead>
              <tbody>
                
                  <tr>
                    <td>args</td>
                    <td class="code"><pre>()</pre></td>
                  </tr>
                
                  <tr>
                    <td>kwargs</td>
                    <td class="code"><pre>{}</pre></td>
                  </tr>
                
                  <tr>
                    <td>request</td>
                    <td class="code"><pre>&lt;ASGIRequest: POST &#x27;/api/math/&#x27;&gt;</pre></td>
                  </tr>
                
                  <tr>
                    <td>view_func</td>
                    <td class="code"><pre>&lt;function View.as_view.&lt;locals&gt;.view at 0x7fc926dd8b80&gt;</pre></td>
                  </tr>
                
              </tbody>
            </table>
            </details>
          
        </li>
      
        
        <li class="frame django">
          
            <code class="fname">/home/docs/checkouts/readthedocs.org/user_builds/django-modern-rest/envs/0.7.0/lib/python3.12/site-packages/django/views/generic/base.py</code>, line 105, in view
          

          
            <div class="context" id="c140501915687296">
              
                <ol start="98" class="pre-context" id="pre140501915687296">
                
                  <li onclick="toggle('pre140501915687296', 'post140501915687296')"><pre>            self = cls(**initkwargs)</pre></li>
                
                  <li onclick="toggle('pre140501915687296', 'post140501915687296')"><pre>            self.setup(request, *args, **kwargs)</pre></li>
                
                  <li onclick="toggle('pre140501915687296', 'post140501915687296')"><pre>            if not hasattr(self, &quot;request&quot;):</pre></li>
                
                  <li onclick="toggle('pre140501915687296', 'post140501915687296')"><pre>                raise AttributeError(</pre></li>
                
                  <li onclick="toggle('pre140501915687296', 'post140501915687296')"><pre>                    &quot;%s instance has no &#x27;request&#x27; attribute. Did you override &quot;</pre></li>
                
                  <li onclick="toggle('pre140501915687296', 'post140501915687296')"><pre>                    &quot;setup() and forget to call super()?&quot; % cls.__name__</pre></li>
                
                  <li onclick="toggle('pre140501915687296', 'post140501915687296')"><pre>                )</pre></li>
                
                </ol>
              
              <ol start="105" class="context-line">
                <li onclick="toggle('pre140501915687296', 'post140501915687296')"><pre>            return self.dispatch(request, *args, **kwargs)
                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^</pre> <span>…</span></li>
              </ol>
              
                <ol start='106' class="post-context" id="post140501915687296">
                  
                  <li onclick="toggle('pre140501915687296', 'post140501915687296')"><pre></pre></li>
                  
                  <li onclick="toggle('pre140501915687296', 'post140501915687296')"><pre>        view.view_class = cls</pre></li>
                  
                  <li onclick="toggle('pre140501915687296', 'post140501915687296')"><pre>        view.view_initkwargs = initkwargs</pre></li>
                  
                  <li onclick="toggle('pre140501915687296', 'post140501915687296')"><pre></pre></li>
                  
                  <li onclick="toggle('pre140501915687296', 'post140501915687296')"><pre>        # __name__ and __qualname__ are intentionally left unchanged as</pre></li>
                  
                  <li onclick="toggle('pre140501915687296', 'post140501915687296')"><pre>        # view_class should be used to robustly determine the name of the view</pre></li>
                  
              </ol>
              
            </div>
          

          
            
              <details>
                <summary class="commands">Local vars</summary>
            
            <table class="vars" id="v140501915687296">
              <thead>
                <tr>
                  <th scope="col">Variable</th>
                  <th scope="col">Value</th>
                </tr>
              </thead>
              <tbody>
                
                  <tr>
                    <td>args</td>
                    <td class="code"><pre>()</pre></td>
                  </tr>
                
                  <tr>
                    <td>cls</td>
                    <td class="code"><pre>&lt;class &#x27;examples.error_handling.endpoint.MathController&#x27;&gt;</pre></td>
                  </tr>
                
                  <tr>
                    <td>initkwargs</td>
                    <td class="code"><pre>{}</pre></td>
                  </tr>
                
                  <tr>
                    <td>kwargs</td>
                    <td class="code"><pre>{}</pre></td>
                  </tr>
                
                  <tr>
                    <td>request</td>
                    <td class="code"><pre>&lt;ASGIRequest: POST &#x27;/api/math/&#x27;&gt;</pre></td>
                  </tr>
                
                  <tr>
                    <td>self</td>
                    <td class="code"><pre>&lt;examples.error_handling.endpoint.MathController object at 0x7fc926eb8380&gt;</pre></td>
                  </tr>
                
              </tbody>
            </table>
            </details>
          
        </li>
      
        
        <li class="frame user">
          
            <code class="fname">/home/docs/checkouts/readthedocs.org/user_builds/django-modern-rest/checkouts/0.7.0/dmr/controller.py</code>, line 241, in dispatch
          

          
            <div class="context" id="c140501914945536">
              
                <ol start="234" class="pre-context" id="pre140501914945536">
                
                  <li onclick="toggle('pre140501914945536', 'post140501914945536')"><pre></pre></li>
                
                  <li onclick="toggle('pre140501914945536', 'post140501914945536')"><pre>        Return 405 if this method is not allowed.</pre></li>
                
                  <li onclick="toggle('pre140501914945536', 'post140501914945536')"><pre>        &quot;&quot;&quot;</pre></li>
                
                  <li onclick="toggle('pre140501914945536', 'post140501914945536')"><pre>        # Fast path for method resolution:</pre></li>
                
                  <li onclick="toggle('pre140501914945536', 'post140501914945536')"><pre>        method: str = request.method  # type: ignore[assignment]</pre></li>
                
                  <li onclick="toggle('pre140501914945536', 'post140501914945536')"><pre>        endpoint = self.api_endpoints.get(method)</pre></li>
                
                  <li onclick="toggle('pre140501914945536', 'post140501914945536')"><pre>        if endpoint is not None:</pre></li>
                
                </ol>
              
              <ol start="241" class="context-line">
                <li onclick="toggle('pre140501914945536', 'post140501914945536')"><pre>            return endpoint(self, *args, **kwargs)
                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^</pre> <span>…</span></li>
              </ol>
              
                <ol start='242' class="post-context" id="post140501914945536">
                  
                  <li onclick="toggle('pre140501914945536', 'post140501914945536')"><pre>        # This return is very special,</pre></li>
                  
                  <li onclick="toggle('pre140501914945536', 'post140501914945536')"><pre>        # since it does not have an attached endpoint.</pre></li>
                  
                  <li onclick="toggle('pre140501914945536', 'post140501914945536')"><pre>        # All other responses are handled on endpoint level</pre></li>
                  
                  <li onclick="toggle('pre140501914945536', 'post140501914945536')"><pre>        # with all the response type validation.</pre></li>
                  
                  <li onclick="toggle('pre140501914945536', 'post140501914945536')"><pre>        return self.handle_method_not_allowed(method)</pre></li>
                  
                  <li onclick="toggle('pre140501914945536', 'post140501914945536')"><pre></pre></li>
                  
              </ol>
              
            </div>
          

          
            
              <details>
                <summary class="commands">Local vars</summary>
            
            <table class="vars" id="v140501914945536">
              <thead>
                <tr>
                  <th scope="col">Variable</th>
                  <th scope="col">Value</th>
                </tr>
              </thead>
              <tbody>
                
                  <tr>
                    <td>args</td>
                    <td class="code"><pre>()</pre></td>
                  </tr>
                
                  <tr>
                    <td>endpoint</td>
                    <td class="code"><pre>&lt;dmr.endpoint.Endpoint object at 0x7fc926dc9310&gt;</pre></td>
                  </tr>
                
                  <tr>
                    <td>kwargs</td>
                    <td class="code"><pre>{}</pre></td>
                  </tr>
                
                  <tr>
                    <td>method</td>
                    <td class="code"><pre>&#x27;POST&#x27;</pre></td>
                  </tr>
                
                  <tr>
                    <td>request</td>
                    <td class="code"><pre>&lt;ASGIRequest: POST &#x27;/api/math/&#x27;&gt;</pre></td>
                  </tr>
                
                  <tr>
                    <td>self</td>
                    <td class="code"><pre>&lt;examples.error_handling.endpoint.MathController object at 0x7fc926eb8380&gt;</pre></td>
                  </tr>
                
              </tbody>
            </table>
            </details>
          
        </li>
      
        
        <li class="frame user">
          
            <code class="fname">/home/docs/checkouts/readthedocs.org/user_builds/django-modern-rest/checkouts/0.7.0/dmr/endpoint.py</code>, line 197, in __call__
          

          
            <div class="context" id="c140501914945664">
              
                <ol start="190" class="pre-context" id="pre140501914945664">
                
                  <li onclick="toggle('pre140501914945664', 'post140501914945664')"><pre>    def __call__(</pre></li>
                
                  <li onclick="toggle('pre140501914945664', 'post140501914945664')"><pre>        self,</pre></li>
                
                  <li onclick="toggle('pre140501914945664', 'post140501914945664')"><pre>        controller: &#x27;Controller[BaseSerializer]&#x27;,</pre></li>
                
                  <li onclick="toggle('pre140501914945664', 'post140501914945664')"><pre>        *args: Any,</pre></li>
                
                  <li onclick="toggle('pre140501914945664', 'post140501914945664')"><pre>        **kwargs: Any,</pre></li>
                
                  <li onclick="toggle('pre140501914945664', 'post140501914945664')"><pre>    ) -&gt; HttpResponseBase:</pre></li>
                
                  <li onclick="toggle('pre140501914945664', 'post140501914945664')"><pre>        &quot;&quot;&quot;Run the endpoint and return the response.&quot;&quot;&quot;</pre></li>
                
                </ol>
              
              <ol start="197" class="context-line">
                <li onclick="toggle('pre140501914945664', 'post140501914945664')"><pre>        return self._func(  # type: ignore[no-any-return]
                    </pre> <span>…</span></li>
              </ol>
              
                <ol start='198' class="post-context" id="post140501914945664">
                  
                  <li onclick="toggle('pre140501914945664', 'post140501914945664')"><pre>            controller,</pre></li>
                  
                  <li onclick="toggle('pre140501914945664', 'post140501914945664')"><pre>            *args,</pre></li>
                  
                  <li onclick="toggle('pre140501914945664', 'post140501914945664')"><pre>            **kwargs,</pre></li>
                  
                  <li onclick="toggle('pre140501914945664', 'post140501914945664')"><pre>        )</pre></li>
                  
                  <li onclick="toggle('pre140501914945664', 'post140501914945664')"><pre></pre></li>
                  
                  <li onclick="toggle('pre140501914945664', 'post140501914945664')"><pre>    def handle_error(</pre></li>
                  
              </ol>
              
            </div>
          

          
            
              <details>
                <summary class="commands">Local vars</summary>
            
            <table class="vars" id="v140501914945664">
              <thead>
                <tr>
                  <th scope="col">Variable</th>
                  <th scope="col">Value</th>
                </tr>
              </thead>
              <tbody>
                
                  <tr>
                    <td>args</td>
                    <td class="code"><pre>()</pre></td>
                  </tr>
                
                  <tr>
                    <td>controller</td>
                    <td class="code"><pre>&lt;examples.error_handling.endpoint.MathController object at 0x7fc926eb8380&gt;</pre></td>
                  </tr>
                
                  <tr>
                    <td>kwargs</td>
                    <td class="code"><pre>{}</pre></td>
                  </tr>
                
                  <tr>
                    <td>self</td>
                    <td class="code"><pre>&lt;dmr.endpoint.Endpoint object at 0x7fc926dc9310&gt;</pre></td>
                  </tr>
                
              </tbody>
            </table>
            </details>
          
        </li>
      
        
        <li class="frame user">
          
            <code class="fname">/home/docs/checkouts/readthedocs.org/user_builds/django-modern-rest/checkouts/0.7.0/dmr/endpoint.py</code>, line 401, in decorator
          

          
            <div class="context" id="c140501914945472">
              
                <ol start="394" class="pre-context" id="pre140501914945472">
                
                  <li onclick="toggle('pre140501914945472', 'post140501914945472')"><pre>                    exc.raw_data,</pre></li>
                
                  <li onclick="toggle('pre140501914945472', 'post140501914945472')"><pre>                    status_code=exc.status_code,</pre></li>
                
                  <li onclick="toggle('pre140501914945472', 'post140501914945472')"><pre>                    headers=exc.headers,</pre></li>
                
                  <li onclick="toggle('pre140501914945472', 'post140501914945472')"><pre>                    cookies=getattr(exc, &#x27;cookies&#x27;, None),</pre></li>
                
                  <li onclick="toggle('pre140501914945472', 'post140501914945472')"><pre>                    renderer=getattr(exc, &#x27;renderer&#x27;, None),</pre></li>
                
                  <li onclick="toggle('pre140501914945472', 'post140501914945472')"><pre>                )</pre></li>
                
                  <li onclick="toggle('pre140501914945472', 'post140501914945472')"><pre>            except Exception as exc:</pre></li>
                
                </ol>
              
              <ol start="401" class="context-line">
                <li onclick="toggle('pre140501914945472', 'post140501914945472')"><pre>                func_result = self.handle_error(controller, exc)
                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^</pre> <span>…</span></li>
              </ol>
              
                <ol start='402' class="post-context" id="post140501914945472">
                  
                  <li onclick="toggle('pre140501914945472', 'post140501914945472')"><pre>            return self._make_http_response(controller, func_result)</pre></li>
                  
                  <li onclick="toggle('pre140501914945472', 'post140501914945472')"><pre></pre></li>
                  
                  <li onclick="toggle('pre140501914945472', 'post140501914945472')"><pre>        return decorator</pre></li>
                  
                  <li onclick="toggle('pre140501914945472', 'post140501914945472')"><pre></pre></li>
                  
                  <li onclick="toggle('pre140501914945472', 'post140501914945472')"><pre>    # Sync checks:</pre></li>
                  
                  <li onclick="toggle('pre140501914945472', 'post140501914945472')"><pre></pre></li>
                  
              </ol>
              
            </div>
          

          
            
              <details>
                <summary class="commands">Local vars</summary>
            
            <table class="vars" id="v140501914945472">
              <thead>
                <tr>
                  <th scope="col">Variable</th>
                  <th scope="col">Value</th>
                </tr>
              </thead>
              <tbody>
                
                  <tr>
                    <td>args</td>
                    <td class="code"><pre>()</pre></td>
                  </tr>
                
                  <tr>
                    <td>context</td>
                    <td class="code"><pre>{&#x27;parsed_body&#x27;: TwoNumbers(left=1, right=0)}</pre></td>
                  </tr>
                
                  <tr>
                    <td>controller</td>
                    <td class="code"><pre>&lt;examples.error_handling.endpoint.MathController object at 0x7fc926eb8380&gt;</pre></td>
                  </tr>
                
                  <tr>
                    <td>func</td>
                    <td class="code"><pre>&lt;function MathController.post at 0x7fc926dd8c20&gt;</pre></td>
                  </tr>
                
                  <tr>
                    <td>kwargs</td>
                    <td class="code"><pre>{}</pre></td>
                  </tr>
                
                  <tr>
                    <td>self</td>
                    <td class="code"><pre>&lt;dmr.endpoint.Endpoint object at 0x7fc926dc9310&gt;</pre></td>
                  </tr>
                
              </tbody>
            </table>
            </details>
          
        </li>
      
        
        <li class="frame user">
          
            <code class="fname">/home/docs/checkouts/readthedocs.org/user_builds/django-modern-rest/checkouts/0.7.0/dmr/endpoint.py</code>, line 236, in handle_error
          

          
            <div class="context" id="c140501914945280">
              
                <ol start="229" class="pre-context" id="pre140501914945280">
                
                  <li onclick="toggle('pre140501914945280', 'post140501914945280')"><pre>            return controller.handle_error(</pre></li>
                
                  <li onclick="toggle('pre140501914945280', 'post140501914945280')"><pre>                self,</pre></li>
                
                  <li onclick="toggle('pre140501914945280', 'post140501914945280')"><pre>                controller,</pre></li>
                
                  <li onclick="toggle('pre140501914945280', 'post140501914945280')"><pre>                exc,</pre></li>
                
                  <li onclick="toggle('pre140501914945280', 'post140501914945280')"><pre>            )</pre></li>
                
                  <li onclick="toggle('pre140501914945280', 'post140501914945280')"><pre>        except Exception:</pre></li>
                
                  <li onclick="toggle('pre140501914945280', 'post140501914945280')"><pre>            # And the last option is to handle error globally:</pre></li>
                
                </ol>
              
              <ol start="236" class="context-line">
                <li onclick="toggle('pre140501914945280', 'post140501914945280')"><pre>            return self._global_error_handler(controller, exc)
                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^</pre> <span>…</span></li>
              </ol>
              
                <ol start='237' class="post-context" id="post140501914945280">
                  
                  <li onclick="toggle('pre140501914945280', 'post140501914945280')"><pre></pre></li>
                  
                  <li onclick="toggle('pre140501914945280', 'post140501914945280')"><pre>    async def handle_async_error(</pre></li>
                  
                  <li onclick="toggle('pre140501914945280', 'post140501914945280')"><pre>        self,</pre></li>
                  
                  <li onclick="toggle('pre140501914945280', 'post140501914945280')"><pre>        controller: &#x27;Controller[BaseSerializer]&#x27;,</pre></li>
                  
                  <li onclick="toggle('pre140501914945280', 'post140501914945280')"><pre>        exc: Exception,</pre></li>
                  
                  <li onclick="toggle('pre140501914945280', 'post140501914945280')"><pre>    ) -&gt; HttpResponse:</pre></li>
                  
              </ol>
              
            </div>
          

          
            
              <details>
                <summary class="commands">Local vars</summary>
            
            <table class="vars" id="v140501914945280">
              <thead>
                <tr>
                  <th scope="col">Variable</th>
                  <th scope="col">Value</th>
                </tr>
              </thead>
              <tbody>
                
                  <tr>
                    <td>controller</td>
                    <td class="code"><pre>&lt;examples.error_handling.endpoint.MathController object at 0x7fc926eb8380&gt;</pre></td>
                  </tr>
                
                  <tr>
                    <td>exc</td>
                    <td class="code"><pre>ZeroDivisionError(&#x27;division by zero&#x27;)</pre></td>
                  </tr>
                
                  <tr>
                    <td>self</td>
                    <td class="code"><pre>&lt;dmr.endpoint.Endpoint object at 0x7fc926dc9310&gt;</pre></td>
                  </tr>
                
              </tbody>
            </table>
            </details>
          
        </li>
      
        
        <li class="frame user">
          
            <code class="fname">/home/docs/checkouts/readthedocs.org/user_builds/django-modern-rest/checkouts/0.7.0/dmr/endpoint.py</code>, line 577, in _global_error_handler
          

          
            <div class="context" id="c140501914944064">
              
                <ol start="570" class="pre-context" id="pre140501914944064">
                
                  <li onclick="toggle('pre140501914944064', 'post140501914944064')"><pre>        exc: Exception,</pre></li>
                
                  <li onclick="toggle('pre140501914944064', 'post140501914944064')"><pre>    ) -&gt; HttpResponse:</pre></li>
                
                  <li onclick="toggle('pre140501914944064', 'post140501914944064')"><pre>        &quot;&quot;&quot;</pre></li>
                
                  <li onclick="toggle('pre140501914944064', 'post140501914944064')"><pre>        Import the global error handling and call it.</pre></li>
                
                  <li onclick="toggle('pre140501914944064', 'post140501914944064')"><pre></pre></li>
                
                  <li onclick="toggle('pre140501914944064', 'post140501914944064')"><pre>        If not class level error handling has happened.</pre></li>
                
                  <li onclick="toggle('pre140501914944064', 'post140501914944064')"><pre>        &quot;&quot;&quot;</pre></li>
                
                </ol>
              
              <ol start="577" class="context-line">
                <li onclick="toggle('pre140501914944064', 'post140501914944064')"><pre>        return resolve_setting(  # type: ignore[no-any-return]
                    ^^^^^^^^^^^^^^^^^</pre> <span>…</span></li>
              </ol>
              
                <ol start='578' class="post-context" id="post140501914944064">
                  
                  <li onclick="toggle('pre140501914944064', 'post140501914944064')"><pre>            Settings.global_error_handler,</pre></li>
                  
                  <li onclick="toggle('pre140501914944064', 'post140501914944064')"><pre>            import_string=True,</pre></li>
                  
                  <li onclick="toggle('pre140501914944064', 'post140501914944064')"><pre>        )(self, controller, exc)</pre></li>
                  
                  <li onclick="toggle('pre140501914944064', 'post140501914944064')"><pre></pre></li>
                  
                  <li onclick="toggle('pre140501914944064', 'post140501914944064')"><pre></pre></li>
                  
                  <li onclick="toggle('pre140501914944064', 'post140501914944064')"><pre>_ParamT = ParamSpec(&#x27;_ParamT&#x27;)</pre></li>
                  
              </ol>
              
            </div>
          

          
            
              <details>
                <summary class="commands">Local vars</summary>
            
            <table class="vars" id="v140501914944064">
              <thead>
                <tr>
                  <th scope="col">Variable</th>
                  <th scope="col">Value</th>
                </tr>
              </thead>
              <tbody>
                
                  <tr>
                    <td>controller</td>
                    <td class="code"><pre>&lt;examples.error_handling.endpoint.MathController object at 0x7fc926eb8380&gt;</pre></td>
                  </tr>
                
                  <tr>
                    <td>exc</td>
                    <td class="code"><pre>ZeroDivisionError(&#x27;division by zero&#x27;)</pre></td>
                  </tr>
                
                  <tr>
                    <td>self</td>
                    <td class="code"><pre>&lt;dmr.endpoint.Endpoint object at 0x7fc926dc9310&gt;</pre></td>
                  </tr>
                
              </tbody>
            </table>
            </details>
          
        </li>
      
        
        <li class="frame user">
          
            <code class="fname">/home/docs/checkouts/readthedocs.org/user_builds/django-modern-rest/checkouts/0.7.0/dmr/endpoint.py</code>, line 229, in handle_error
          

          
            <div class="context" id="c140501917400320">
              
                <ol start="222" class="pre-context" id="pre140501917400320">
                
                  <li onclick="toggle('pre140501917400320', 'post140501917400320')"><pre>                )</pre></li>
                
                  <li onclick="toggle('pre140501917400320', 'post140501917400320')"><pre>            except Exception:  # noqa: S110</pre></li>
                
                  <li onclick="toggle('pre140501917400320', 'post140501917400320')"><pre>                # We don&#x27;t use `suppress` here for speed.</pre></li>
                
                  <li onclick="toggle('pre140501917400320', 'post140501917400320')"><pre>                pass  # noqa: WPS420</pre></li>
                
                  <li onclick="toggle('pre140501917400320', 'post140501917400320')"><pre>        # Per-endpoint error handler didn&#x27;t work.</pre></li>
                
                  <li onclick="toggle('pre140501917400320', 'post140501917400320')"><pre>        # Now, try the per-controller one.</pre></li>
                
                  <li onclick="toggle('pre140501917400320', 'post140501917400320')"><pre>        try:</pre></li>
                
                </ol>
              
              <ol start="229" class="context-line">
                <li onclick="toggle('pre140501917400320', 'post140501917400320')"><pre>            return controller.handle_error(
                        </pre> <span>…</span></li>
              </ol>
              
                <ol start='230' class="post-context" id="post140501917400320">
                  
                  <li onclick="toggle('pre140501917400320', 'post140501917400320')"><pre>                self,</pre></li>
                  
                  <li onclick="toggle('pre140501917400320', 'post140501917400320')"><pre>                controller,</pre></li>
                  
                  <li onclick="toggle('pre140501917400320', 'post140501917400320')"><pre>                exc,</pre></li>
                  
                  <li onclick="toggle('pre140501917400320', 'post140501917400320')"><pre>            )</pre></li>
                  
                  <li onclick="toggle('pre140501917400320', 'post140501917400320')"><pre>        except Exception:</pre></li>
                  
                  <li onclick="toggle('pre140501917400320', 'post140501917400320')"><pre>            # And the last option is to handle error globally:</pre></li>
                  
              </ol>
              
            </div>
          

          
            
              <details>
                <summary class="commands">Local vars</summary>
            
            <table class="vars" id="v140501917400320">
              <thead>
                <tr>
                  <th scope="col">Variable</th>
                  <th scope="col">Value</th>
                </tr>
              </thead>
              <tbody>
                
                  <tr>
                    <td>controller</td>
                    <td class="code"><pre>&lt;examples.error_handling.endpoint.MathController object at 0x7fc926eb8380&gt;</pre></td>
                  </tr>
                
                  <tr>
                    <td>exc</td>
                    <td class="code"><pre>ZeroDivisionError(&#x27;division by zero&#x27;)</pre></td>
                  </tr>
                
                  <tr>
                    <td>self</td>
                    <td class="code"><pre>&lt;dmr.endpoint.Endpoint object at 0x7fc926dc9310&gt;</pre></td>
                  </tr>
                
              </tbody>
            </table>
            </details>
          
        </li>
      
        
        <li class="frame user">
          
            <code class="fname">/home/docs/checkouts/readthedocs.org/user_builds/django-modern-rest/checkouts/0.7.0/dmr/endpoint.py</code>, line 391, in decorator
          

          
            <div class="context" id="c140501914927616">
              
                <ol start="384" class="pre-context" id="pre140501914927616">
                
                  <li onclick="toggle('pre140501914927616', 'post140501914927616')"><pre>                # Run checks:</pre></li>
                
                  <li onclick="toggle('pre140501914927616', 'post140501914927616')"><pre>                self._run_checks(controller)</pre></li>
                
                  <li onclick="toggle('pre140501914927616', 'post140501914927616')"><pre></pre></li>
                
                  <li onclick="toggle('pre140501914927616', 'post140501914927616')"><pre>                # Parse request:</pre></li>
                
                  <li onclick="toggle('pre140501914927616', 'post140501914927616')"><pre>                context = self._serializer_context(self, controller)</pre></li>
                
                  <li onclick="toggle('pre140501914927616', 'post140501914927616')"><pre></pre></li>
                
                  <li onclick="toggle('pre140501914927616', 'post140501914927616')"><pre>                # Return response:</pre></li>
                
                </ol>
              
              <ol start="391" class="context-line">
                <li onclick="toggle('pre140501914927616', 'post140501914927616')"><pre>                func_result = func(controller, **context)
                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^</pre> <span>…</span></li>
              </ol>
              
                <ol start='392' class="post-context" id="post140501914927616">
                  
                  <li onclick="toggle('pre140501914927616', 'post140501914927616')"><pre>            except (APIError, APIRedirectError) as exc:</pre></li>
                  
                  <li onclick="toggle('pre140501914927616', 'post140501914927616')"><pre>                func_result = controller.to_error(</pre></li>
                  
                  <li onclick="toggle('pre140501914927616', 'post140501914927616')"><pre>                    exc.raw_data,</pre></li>
                  
                  <li onclick="toggle('pre140501914927616', 'post140501914927616')"><pre>                    status_code=exc.status_code,</pre></li>
                  
                  <li onclick="toggle('pre140501914927616', 'post140501914927616')"><pre>                    headers=exc.headers,</pre></li>
                  
                  <li onclick="toggle('pre140501914927616', 'post140501914927616')"><pre>                    cookies=getattr(exc, &#x27;cookies&#x27;, None),</pre></li>
                  
              </ol>
              
            </div>
          

          
            
              <details>
                <summary class="commands">Local vars</summary>
            
            <table class="vars" id="v140501914927616">
              <thead>
                <tr>
                  <th scope="col">Variable</th>
                  <th scope="col">Value</th>
                </tr>
              </thead>
              <tbody>
                
                  <tr>
                    <td>args</td>
                    <td class="code"><pre>()</pre></td>
                  </tr>
                
                  <tr>
                    <td>context</td>
                    <td class="code"><pre>{&#x27;parsed_body&#x27;: TwoNumbers(left=1, right=0)}</pre></td>
                  </tr>
                
                  <tr>
                    <td>controller</td>
                    <td class="code"><pre>&lt;examples.error_handling.endpoint.MathController object at 0x7fc926eb8380&gt;</pre></td>
                  </tr>
                
                  <tr>
                    <td>func</td>
                    <td class="code"><pre>&lt;function MathController.post at 0x7fc926dd8c20&gt;</pre></td>
                  </tr>
                
                  <tr>
                    <td>kwargs</td>
                    <td class="code"><pre>{}</pre></td>
                  </tr>
                
                  <tr>
                    <td>self</td>
                    <td class="code"><pre>&lt;dmr.endpoint.Endpoint object at 0x7fc926dc9310&gt;</pre></td>
                  </tr>
                
              </tbody>
            </table>
            </details>
          
        </li>
      
        
        <li class="frame user">
          
            <code class="fname">/home/docs/checkouts/readthedocs.org/user_builds/django-modern-rest/checkouts/0.7.0/docs/examples/error_handling/endpoint.py</code>, line 45, in post
          

          
            <div class="context" id="c140501914935360">
              
                <ol start="38" class="pre-context" id="pre140501914935360">
                
                  <li onclick="toggle('pre140501914935360', 'post140501914935360')"><pre>    ) -&gt; float:  # &lt;- has custom error handling</pre></li>
                
                  <li onclick="toggle('pre140501914935360', 'post140501914935360')"><pre>        return parsed_body.left / parsed_body.right</pre></li>
                
                  <li onclick="toggle('pre140501914935360', 'post140501914935360')"><pre></pre></li>
                
                  <li onclick="toggle('pre140501914935360', 'post140501914935360')"><pre>    def post(</pre></li>
                
                  <li onclick="toggle('pre140501914935360', 'post140501914935360')"><pre>        self,</pre></li>
                
                  <li onclick="toggle('pre140501914935360', 'post140501914935360')"><pre>        parsed_body: Body[TwoNumbers],</pre></li>
                
                  <li onclick="toggle('pre140501914935360', 'post140501914935360')"><pre>    ) -&gt; float:  # &lt;- has only default error handling</pre></li>
                
                </ol>
              
              <ol start="45" class="context-line">
                <li onclick="toggle('pre140501914935360', 'post140501914935360')"><pre>        return parsed_body.left / parsed_body.right
                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^</pre> <span>…</span></li>
              </ol>
              
                <ol start='46' class="post-context" id="post140501914935360">
                  
                  <li onclick="toggle('pre140501914935360', 'post140501914935360')"><pre></pre></li>
                  
                  <li onclick="toggle('pre140501914935360', 'post140501914935360')"><pre></pre></li>
                  
                  <li onclick="toggle('pre140501914935360', 'post140501914935360')"><pre># run: {&quot;controller&quot;: &quot;MathController&quot;, &quot;method&quot;: &quot;patch&quot;, &quot;body&quot;: {&quot;left&quot;: 1, &quot;right&quot;: 0}, &quot;url&quot;: &quot;/api/math/&quot;, &quot;curl_args&quot;: [&quot;-D&quot;, &quot;-&quot;], &quot;assert-error-text&quot;: &quot;division by zero&quot;, &quot;fail-with-body&quot;: false}  # noqa: ERA001, E501</pre></li>
                  
                  <li onclick="toggle('pre140501914935360', 'post140501914935360')"><pre># run: {&quot;controller&quot;: &quot;MathController&quot;, &quot;method&quot;: &quot;post&quot;, &quot;body&quot;: {&quot;left&quot;: 1, &quot;right&quot;: 0}, &quot;url&quot;: &quot;/api/math/&quot;, &quot;curl_args&quot;: [&quot;-D&quot;, &quot;-&quot;], &quot;assert-error-text&quot;: &quot;Internal server error&quot;, &quot;fail-with-body&quot;: false}  # noqa: ERA001, E501</pre></li>
                  
              </ol>
              
            </div>
          

          
            
              <details>
                <summary class="commands">Local vars</summary>
            
            <table class="vars" id="v140501914935360">
              <thead>
                <tr>
                  <th scope="col">Variable</th>
                  <th scope="col">Value</th>
                </tr>
              </thead>
              <tbody>
                
                  <tr>
                    <td>parsed_body</td>
                    <td class="code"><pre>TwoNumbers(left=1, right=0)</pre></td>
                  </tr>
                
                  <tr>
                    <td>self</td>
                    <td class="code"><pre>&lt;examples.error_handling.endpoint.MathController object at 0x7fc926eb8380&gt;</pre></td>
                  </tr>
                
              </tbody>
            </table>
            </details>
          
        </li>
      
    </ul>
  </div>

  <form action="https://dpaste.com/" name="pasteform" id="pasteform" method="post">
  <div id="pastebinTraceback" class="pastebin">
    <input type="hidden" name="language" value="PythonConsole">
    <input type="hidden" name="title"
      value="ZeroDivisionError at /api/math/">
    <input type="hidden" name="source" value="Django Dpaste Agent">
    <input type="hidden" name="poster" value="Django">
    <textarea name="content" id="traceback_area" cols="140" rows="25">
Environment:


Request Method: POST
Request URL: http://127.0.0.1:45355/api/math/

Django Version: 5.2.13
Python Version: 3.12.10
Installed Applications:
[&#x27;django.contrib.auth&#x27;,
 &#x27;django.contrib.sessions&#x27;,
 &#x27;django.contrib.contenttypes&#x27;,
 &#x27;dmr&#x27;,
 &#x27;dmr.security.jwt.blocklist&#x27;,
 &#x27;server.apps.model_simple&#x27;,
 &#x27;server.apps.model_fk&#x27;]
Installed Middleware:
[&#x27;django.middleware.security.SecurityMiddleware&#x27;,
 &#x27;django.contrib.sessions.middleware.SessionMiddleware&#x27;,
 &#x27;django.middleware.common.CommonMiddleware&#x27;,
 &#x27;django.middleware.csrf.CsrfViewMiddleware&#x27;,
 &#x27;django.contrib.auth.middleware.AuthenticationMiddleware&#x27;,
 &#x27;django.middleware.locale.LocaleMiddleware&#x27;,
 &#x27;django.contrib.messages.middleware.MessageMiddleware&#x27;,
 &#x27;django.middleware.clickjacking.XFrameOptionsMiddleware&#x27;]



Traceback (most recent call last):
  File "/home/docs/checkouts/readthedocs.org/user_builds/django-modern-rest/envs/0.7.0/lib/python3.12/site-packages/django/core/handlers/exception.py", line 42, in inner
    response = await get_response(request)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/docs/checkouts/readthedocs.org/user_builds/django-modern-rest/envs/0.7.0/lib/python3.12/site-packages/django/core/handlers/base.py", line 253, in _get_response_async
    response = await wrapped_callback(
               
  File "/home/docs/.asdf/installs/python/3.12.10/lib/python3.12/concurrent/futures/thread.py", line 59, in run
    result = self.fn(*self.args, **self.kwargs)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/docs/checkouts/readthedocs.org/user_builds/django-modern-rest/envs/0.7.0/lib/python3.12/site-packages/django/views/decorators/csrf.py", line 65, in _view_wrapper
    return view_func(request, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/docs/checkouts/readthedocs.org/user_builds/django-modern-rest/envs/0.7.0/lib/python3.12/site-packages/django/views/generic/base.py", line 105, in view
    return self.dispatch(request, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/docs/checkouts/readthedocs.org/user_builds/django-modern-rest/checkouts/0.7.0/dmr/controller.py", line 241, in dispatch
    return endpoint(self, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/docs/checkouts/readthedocs.org/user_builds/django-modern-rest/checkouts/0.7.0/dmr/endpoint.py", line 197, in __call__
    return self._func(  # type: ignore[no-any-return]
           
  File "/home/docs/checkouts/readthedocs.org/user_builds/django-modern-rest/checkouts/0.7.0/dmr/endpoint.py", line 401, in decorator
    func_result = self.handle_error(controller, exc)
                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/docs/checkouts/readthedocs.org/user_builds/django-modern-rest/checkouts/0.7.0/dmr/endpoint.py", line 236, in handle_error
    return self._global_error_handler(controller, exc)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/docs/checkouts/readthedocs.org/user_builds/django-modern-rest/checkouts/0.7.0/dmr/endpoint.py", line 577, in _global_error_handler
    return resolve_setting(  # type: ignore[no-any-return]
           ^^^^^^^^^^^^^^^^^
  File "/home/docs/checkouts/readthedocs.org/user_builds/django-modern-rest/checkouts/0.7.0/dmr/endpoint.py", line 229, in handle_error
    return controller.handle_error(
           
  File "/home/docs/checkouts/readthedocs.org/user_builds/django-modern-rest/checkouts/0.7.0/dmr/endpoint.py", line 391, in decorator
    func_result = func(controller, **context)
                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/docs/checkouts/readthedocs.org/user_builds/django-modern-rest/checkouts/0.7.0/docs/examples/error_handling/endpoint.py", line 45, in post
    return parsed_body.left / parsed_body.right
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Exception Type: ZeroDivisionError at /api/math/
Exception Value: division by zero
</textarea>
  <br><br>
  <input type="submit" value="Share this traceback on a public website">
  </div>
</form>

</div>


<div id="requestinfo">
  <h2>Request information</h2>


  
    <h3 id="user-info">USER</h3>
    <p>AnonymousUser</p>
  

  <h3 id="get-info">GET</h3>
  
    <p>No GET data</p>
  

  <h3 id="post-info">POST</h3>
  
    <p>No POST data</p>
  

  <h3 id="files-info">FILES</h3>
  
    <p>No FILES data</p>
  

  <h3 id="cookie-info">COOKIES</h3>
  
    <p>No cookie data</p>
  

  <h3 id="meta-info">META</h3>
  <table class="req">
    <thead>
      <tr>
        <th scope="col">Variable</th>
        <th scope="col">Value</th>
      </tr>
    </thead>
    <tbody>
      
        <tr>
          <td>CONTENT_LENGTH</td>
          <td class="code"><pre>&#x27;23&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>CONTENT_TYPE</td>
          <td class="code"><pre>&#x27;application/json&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>HTTP_ACCEPT</td>
          <td class="code"><pre>&#x27;*/*&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>HTTP_HOST</td>
          <td class="code"><pre>&#x27;127.0.0.1:45355&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>HTTP_USER_AGENT</td>
          <td class="code"><pre>&#x27;curl/7.81.0&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>PATH_INFO</td>
          <td class="code"><pre>&#x27;/api/math/&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>QUERY_STRING</td>
          <td class="code"><pre>&#x27;&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>REMOTE_ADDR</td>
          <td class="code"><pre>&#x27;127.0.0.1&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>REMOTE_HOST</td>
          <td class="code"><pre>&#x27;127.0.0.1&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>REMOTE_PORT</td>
          <td class="code"><pre>51890</pre></td>
        </tr>
      
        <tr>
          <td>REQUEST_METHOD</td>
          <td class="code"><pre>&#x27;POST&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>SCRIPT_NAME</td>
          <td class="code"><pre>&#x27;&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>SERVER_NAME</td>
          <td class="code"><pre>&#x27;127.0.0.1&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>SERVER_PORT</td>
          <td class="code"><pre>&#x27;45355&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>wsgi.multiprocess</td>
          <td class="code"><pre>True</pre></td>
        </tr>
      
        <tr>
          <td>wsgi.multithread</td>
          <td class="code"><pre>True</pre></td>
        </tr>
      
    </tbody>
  </table>


  <h3 id="settings-info">Settings</h3>
  <h4>Using settings module <code></code></h4>
  <table class="req">
    <thead>
      <tr>
        <th scope="col">Setting</th>
        <th scope="col">Value</th>
      </tr>
    </thead>
    <tbody>
      
        <tr>
          <td>ABSOLUTE_URL_OVERRIDES</td>
          <td class="code"><pre>{}</pre></td>
        </tr>
      
        <tr>
          <td>ADMINS</td>
          <td class="code"><pre>[]</pre></td>
        </tr>
      
        <tr>
          <td>ALLOWED_HOSTS</td>
          <td class="code"><pre>[&#x27;*&#x27;]</pre></td>
        </tr>
      
        <tr>
          <td>APPEND_SLASH</td>
          <td class="code"><pre>True</pre></td>
        </tr>
      
        <tr>
          <td>AUTHENTICATION_BACKENDS</td>
          <td class="code"><pre>&#x27;********************&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>AUTH_PASSWORD_VALIDATORS</td>
          <td class="code"><pre>&#x27;********************&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>AUTH_USER_MODEL</td>
          <td class="code"><pre>&#x27;********************&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>CACHES</td>
          <td class="code"><pre>{&#x27;default&#x27;: {&#x27;BACKEND&#x27;: &#x27;django.core.cache.backends.filebased.FileBasedCache&#x27;,
             &#x27;LOCATION&#x27;: &#x27;/home/docs/checkouts/readthedocs.org/user_builds/django-modern-rest/checkouts/0.7.0/docs/_build/default.cache&#x27;},
 &#x27;throttling&#x27;: {&#x27;BACKEND&#x27;: &#x27;django.core.cache.backends.filebased.FileBasedCache&#x27;,
                &#x27;LOCATION&#x27;: &#x27;/home/docs/checkouts/readthedocs.org/user_builds/django-modern-rest/checkouts/0.7.0/docs/_build/throttling.cache&#x27;}}</pre></td>
        </tr>
      
        <tr>
          <td>CACHE_MIDDLEWARE_ALIAS</td>
          <td class="code"><pre>&#x27;default&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>CACHE_MIDDLEWARE_KEY_PREFIX</td>
          <td class="code"><pre>&#x27;********************&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>CACHE_MIDDLEWARE_SECONDS</td>
          <td class="code"><pre>600</pre></td>
        </tr>
      
        <tr>
          <td>CSRF_COOKIE_AGE</td>
          <td class="code"><pre>31449600</pre></td>
        </tr>
      
        <tr>
          <td>CSRF_COOKIE_DOMAIN</td>
          <td class="code"><pre>None</pre></td>
        </tr>
      
        <tr>
          <td>CSRF_COOKIE_HTTPONLY</td>
          <td class="code"><pre>False</pre></td>
        </tr>
      
        <tr>
          <td>CSRF_COOKIE_NAME</td>
          <td class="code"><pre>&#x27;csrftoken&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>CSRF_COOKIE_PATH</td>
          <td class="code"><pre>&#x27;/&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>CSRF_COOKIE_SAMESITE</td>
          <td class="code"><pre>&#x27;Lax&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>CSRF_COOKIE_SECURE</td>
          <td class="code"><pre>False</pre></td>
        </tr>
      
        <tr>
          <td>CSRF_FAILURE_VIEW</td>
          <td class="code"><pre>&#x27;django.views.csrf.csrf_failure&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>CSRF_HEADER_NAME</td>
          <td class="code"><pre>&#x27;HTTP_X_CSRFTOKEN&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>CSRF_TRUSTED_ORIGINS</td>
          <td class="code"><pre>[]</pre></td>
        </tr>
      
        <tr>
          <td>CSRF_USE_SESSIONS</td>
          <td class="code"><pre>False</pre></td>
        </tr>
      
        <tr>
          <td>DATABASES</td>
          <td class="code"><pre>{&#x27;default&#x27;: {&#x27;ATOMIC_REQUESTS&#x27;: False,
             &#x27;AUTOCOMMIT&#x27;: True,
             &#x27;CONN_HEALTH_CHECKS&#x27;: False,
             &#x27;CONN_MAX_AGE&#x27;: 0,
             &#x27;ENGINE&#x27;: &#x27;django.db.backends.sqlite3&#x27;,
             &#x27;HOST&#x27;: &#x27;&#x27;,
             &#x27;NAME&#x27;: &#x27;_build/test.db&#x27;,
             &#x27;OPTIONS&#x27;: {},
             &#x27;PASSWORD&#x27;: &#x27;********************&#x27;,
             &#x27;PORT&#x27;: &#x27;&#x27;,
             &#x27;TEST&#x27;: {&#x27;CHARSET&#x27;: None,
                      &#x27;COLLATION&#x27;: None,
                      &#x27;MIGRATE&#x27;: True,
                      &#x27;MIRROR&#x27;: None,
                      &#x27;NAME&#x27;: None},
             &#x27;TIME_ZONE&#x27;: None,
             &#x27;USER&#x27;: &#x27;&#x27;}}</pre></td>
        </tr>
      
        <tr>
          <td>DATABASE_ROUTERS</td>
          <td class="code"><pre>[]</pre></td>
        </tr>
      
        <tr>
          <td>DATA_UPLOAD_MAX_MEMORY_SIZE</td>
          <td class="code"><pre>2621440</pre></td>
        </tr>
      
        <tr>
          <td>DATA_UPLOAD_MAX_NUMBER_FIELDS</td>
          <td class="code"><pre>1000</pre></td>
        </tr>
      
        <tr>
          <td>DATA_UPLOAD_MAX_NUMBER_FILES</td>
          <td class="code"><pre>100</pre></td>
        </tr>
      
        <tr>
          <td>DATETIME_FORMAT</td>
          <td class="code"><pre>&#x27;N j, Y, P&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>DATETIME_INPUT_FORMATS</td>
          <td class="code"><pre>[&#x27;%Y-%m-%d %H:%M:%S&#x27;,
 &#x27;%Y-%m-%d %H:%M:%S.%f&#x27;,
 &#x27;%Y-%m-%d %H:%M&#x27;,
 &#x27;%m/%d/%Y %H:%M:%S&#x27;,
 &#x27;%m/%d/%Y %H:%M:%S.%f&#x27;,
 &#x27;%m/%d/%Y %H:%M&#x27;,
 &#x27;%m/%d/%y %H:%M:%S&#x27;,
 &#x27;%m/%d/%y %H:%M:%S.%f&#x27;,
 &#x27;%m/%d/%y %H:%M&#x27;]</pre></td>
        </tr>
      
        <tr>
          <td>DATE_FORMAT</td>
          <td class="code"><pre>&#x27;N j, Y&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>DATE_INPUT_FORMATS</td>
          <td class="code"><pre>[&#x27;%Y-%m-%d&#x27;,
 &#x27;%m/%d/%Y&#x27;,
 &#x27;%m/%d/%y&#x27;,
 &#x27;%b %d %Y&#x27;,
 &#x27;%b %d, %Y&#x27;,
 &#x27;%d %b %Y&#x27;,
 &#x27;%d %b, %Y&#x27;,
 &#x27;%B %d %Y&#x27;,
 &#x27;%B %d, %Y&#x27;,
 &#x27;%d %B %Y&#x27;,
 &#x27;%d %B, %Y&#x27;]</pre></td>
        </tr>
      
        <tr>
          <td>DEBUG</td>
          <td class="code"><pre>True</pre></td>
        </tr>
      
        <tr>
          <td>DEBUG_PROPAGATE_EXCEPTIONS</td>
          <td class="code"><pre>False</pre></td>
        </tr>
      
        <tr>
          <td>DECIMAL_SEPARATOR</td>
          <td class="code"><pre>&#x27;.&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>DEFAULT_AUTO_FIELD</td>
          <td class="code"><pre>&#x27;django.db.models.BigAutoField&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>DEFAULT_CHARSET</td>
          <td class="code"><pre>&#x27;utf-8&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>DEFAULT_EXCEPTION_REPORTER</td>
          <td class="code"><pre>&#x27;django.views.debug.ExceptionReporter&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>DEFAULT_EXCEPTION_REPORTER_FILTER</td>
          <td class="code"><pre>&#x27;django.views.debug.SafeExceptionReporterFilter&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>DEFAULT_FROM_EMAIL</td>
          <td class="code"><pre>&#x27;webmaster@localhost&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>DEFAULT_INDEX_TABLESPACE</td>
          <td class="code"><pre>&#x27;&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>DEFAULT_TABLESPACE</td>
          <td class="code"><pre>&#x27;&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>DISALLOWED_USER_AGENTS</td>
          <td class="code"><pre>[]</pre></td>
        </tr>
      
        <tr>
          <td>EMAIL_BACKEND</td>
          <td class="code"><pre>&#x27;django.core.mail.backends.smtp.EmailBackend&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>EMAIL_HOST</td>
          <td class="code"><pre>&#x27;localhost&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>EMAIL_HOST_PASSWORD</td>
          <td class="code"><pre>&#x27;********************&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>EMAIL_HOST_USER</td>
          <td class="code"><pre>&#x27;&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>EMAIL_PORT</td>
          <td class="code"><pre>25</pre></td>
        </tr>
      
        <tr>
          <td>EMAIL_SSL_CERTFILE</td>
          <td class="code"><pre>None</pre></td>
        </tr>
      
        <tr>
          <td>EMAIL_SSL_KEYFILE</td>
          <td class="code"><pre>&#x27;********************&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>EMAIL_SUBJECT_PREFIX</td>
          <td class="code"><pre>&#x27;[Django] &#x27;</pre></td>
        </tr>
      
        <tr>
          <td>EMAIL_TIMEOUT</td>
          <td class="code"><pre>None</pre></td>
        </tr>
      
        <tr>
          <td>EMAIL_USE_LOCALTIME</td>
          <td class="code"><pre>False</pre></td>
        </tr>
      
        <tr>
          <td>EMAIL_USE_SSL</td>
          <td class="code"><pre>False</pre></td>
        </tr>
      
        <tr>
          <td>EMAIL_USE_TLS</td>
          <td class="code"><pre>False</pre></td>
        </tr>
      
        <tr>
          <td>FILE_UPLOAD_DIRECTORY_PERMISSIONS</td>
          <td class="code"><pre>None</pre></td>
        </tr>
      
        <tr>
          <td>FILE_UPLOAD_HANDLERS</td>
          <td class="code"><pre>[&#x27;django.core.files.uploadhandler.MemoryFileUploadHandler&#x27;,
 &#x27;django.core.files.uploadhandler.TemporaryFileUploadHandler&#x27;]</pre></td>
        </tr>
      
        <tr>
          <td>FILE_UPLOAD_MAX_MEMORY_SIZE</td>
          <td class="code"><pre>2621440</pre></td>
        </tr>
      
        <tr>
          <td>FILE_UPLOAD_PERMISSIONS</td>
          <td class="code"><pre>420</pre></td>
        </tr>
      
        <tr>
          <td>FILE_UPLOAD_TEMP_DIR</td>
          <td class="code"><pre>None</pre></td>
        </tr>
      
        <tr>
          <td>FIRST_DAY_OF_WEEK</td>
          <td class="code"><pre>0</pre></td>
        </tr>
      
        <tr>
          <td>FIXTURE_DIRS</td>
          <td class="code"><pre>[]</pre></td>
        </tr>
      
        <tr>
          <td>FORCE_SCRIPT_NAME</td>
          <td class="code"><pre>None</pre></td>
        </tr>
      
        <tr>
          <td>FORMAT_MODULE_PATH</td>
          <td class="code"><pre>None</pre></td>
        </tr>
      
        <tr>
          <td>FORMS_URLFIELD_ASSUME_HTTPS</td>
          <td class="code"><pre>False</pre></td>
        </tr>
      
        <tr>
          <td>FORM_RENDERER</td>
          <td class="code"><pre>&#x27;django.forms.renderers.DjangoTemplates&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>HTTP_BASIC_PASSWORD</td>
          <td class="code"><pre>&#x27;********************&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>HTTP_BASIC_USERNAME</td>
          <td class="code"><pre>&#x27;admin&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>IGNORABLE_404_URLS</td>
          <td class="code"><pre>[]</pre></td>
        </tr>
      
        <tr>
          <td>INSTALLED_APPS</td>
          <td class="code"><pre>[&#x27;django.contrib.auth&#x27;,
 &#x27;django.contrib.sessions&#x27;,
 &#x27;django.contrib.contenttypes&#x27;,
 &#x27;dmr&#x27;,
 &#x27;dmr.security.jwt.blocklist&#x27;,
 &#x27;server.apps.model_simple&#x27;,
 &#x27;server.apps.model_fk&#x27;]</pre></td>
        </tr>
      
        <tr>
          <td>INTERNAL_IPS</td>
          <td class="code"><pre>[]</pre></td>
        </tr>
      
        <tr>
          <td>LANGUAGES</td>
          <td class="code"><pre>((&#x27;en&#x27;, &#x27;English&#x27;), (&#x27;ru&#x27;, &#x27;Russian&#x27;))</pre></td>
        </tr>
      
        <tr>
          <td>LANGUAGES_BIDI</td>
          <td class="code"><pre>[&#x27;he&#x27;, &#x27;ar&#x27;, &#x27;ar-dz&#x27;, &#x27;ckb&#x27;, &#x27;fa&#x27;, &#x27;ug&#x27;, &#x27;ur&#x27;]</pre></td>
        </tr>
      
        <tr>
          <td>LANGUAGE_CODE</td>
          <td class="code"><pre>&#x27;en-us&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>LANGUAGE_COOKIE_AGE</td>
          <td class="code"><pre>None</pre></td>
        </tr>
      
        <tr>
          <td>LANGUAGE_COOKIE_DOMAIN</td>
          <td class="code"><pre>None</pre></td>
        </tr>
      
        <tr>
          <td>LANGUAGE_COOKIE_HTTPONLY</td>
          <td class="code"><pre>False</pre></td>
        </tr>
      
        <tr>
          <td>LANGUAGE_COOKIE_NAME</td>
          <td class="code"><pre>&#x27;django_language&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>LANGUAGE_COOKIE_PATH</td>
          <td class="code"><pre>&#x27;/&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>LANGUAGE_COOKIE_SAMESITE</td>
          <td class="code"><pre>None</pre></td>
        </tr>
      
        <tr>
          <td>LANGUAGE_COOKIE_SECURE</td>
          <td class="code"><pre>False</pre></td>
        </tr>
      
        <tr>
          <td>LOCALE_PATHS</td>
          <td class="code"><pre>[&#x27;/home/docs/checkouts/readthedocs.org/user_builds/django-modern-rest/checkouts/0.7.0/dmr/locale&#x27;]</pre></td>
        </tr>
      
        <tr>
          <td>LOGGING</td>
          <td class="code"><pre>{}</pre></td>
        </tr>
      
        <tr>
          <td>LOGGING_CONFIG</td>
          <td class="code"><pre>None</pre></td>
        </tr>
      
        <tr>
          <td>LOGIN_REDIRECT_URL</td>
          <td class="code"><pre>&#x27;/accounts/profile/&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>LOGIN_URL</td>
          <td class="code"><pre>&#x27;/accounts/login/&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>LOGOUT_REDIRECT_URL</td>
          <td class="code"><pre>None</pre></td>
        </tr>
      
        <tr>
          <td>MANAGERS</td>
          <td class="code"><pre>[]</pre></td>
        </tr>
      
        <tr>
          <td>MEDIA_ROOT</td>
          <td class="code"><pre>&#x27;&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>MEDIA_URL</td>
          <td class="code"><pre>&#x27;/&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>MESSAGE_STORAGE</td>
          <td class="code"><pre>&#x27;django.contrib.messages.storage.fallback.FallbackStorage&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>MIDDLEWARE</td>
          <td class="code"><pre>[&#x27;django.middleware.security.SecurityMiddleware&#x27;,
 &#x27;django.contrib.sessions.middleware.SessionMiddleware&#x27;,
 &#x27;django.middleware.common.CommonMiddleware&#x27;,
 &#x27;django.middleware.csrf.CsrfViewMiddleware&#x27;,
 &#x27;django.contrib.auth.middleware.AuthenticationMiddleware&#x27;,
 &#x27;django.middleware.locale.LocaleMiddleware&#x27;,
 &#x27;django.contrib.messages.middleware.MessageMiddleware&#x27;,
 &#x27;django.middleware.clickjacking.XFrameOptionsMiddleware&#x27;]</pre></td>
        </tr>
      
        <tr>
          <td>MIGRATION_MODULES</td>
          <td class="code"><pre>{}</pre></td>
        </tr>
      
        <tr>
          <td>MONTH_DAY_FORMAT</td>
          <td class="code"><pre>&#x27;F j&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>NUMBER_GROUPING</td>
          <td class="code"><pre>0</pre></td>
        </tr>
      
        <tr>
          <td>PASSWORD_HASHERS</td>
          <td class="code"><pre>&#x27;********************&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>PASSWORD_RESET_TIMEOUT</td>
          <td class="code"><pre>&#x27;********************&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>PREPEND_WWW</td>
          <td class="code"><pre>False</pre></td>
        </tr>
      
        <tr>
          <td>ROOT_URLCONF</td>
          <td class="code"><pre>&#x27;url_conf&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>SECRET_KEY</td>
          <td class="code"><pre>&#x27;********************&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>SECRET_KEY_FALLBACKS</td>
          <td class="code"><pre>&#x27;********************&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>SECURE_CONTENT_TYPE_NOSNIFF</td>
          <td class="code"><pre>True</pre></td>
        </tr>
      
        <tr>
          <td>SECURE_CROSS_ORIGIN_OPENER_POLICY</td>
          <td class="code"><pre>&#x27;same-origin&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>SECURE_HSTS_INCLUDE_SUBDOMAINS</td>
          <td class="code"><pre>False</pre></td>
        </tr>
      
        <tr>
          <td>SECURE_HSTS_PRELOAD</td>
          <td class="code"><pre>False</pre></td>
        </tr>
      
        <tr>
          <td>SECURE_HSTS_SECONDS</td>
          <td class="code"><pre>0</pre></td>
        </tr>
      
        <tr>
          <td>SECURE_PROXY_SSL_HEADER</td>
          <td class="code"><pre>None</pre></td>
        </tr>
      
        <tr>
          <td>SECURE_REDIRECT_EXEMPT</td>
          <td class="code"><pre>[]</pre></td>
        </tr>
      
        <tr>
          <td>SECURE_REFERRER_POLICY</td>
          <td class="code"><pre>&#x27;same-origin&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>SECURE_SSL_HOST</td>
          <td class="code"><pre>None</pre></td>
        </tr>
      
        <tr>
          <td>SECURE_SSL_REDIRECT</td>
          <td class="code"><pre>False</pre></td>
        </tr>
      
        <tr>
          <td>SERVER_EMAIL</td>
          <td class="code"><pre>&#x27;root@localhost&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>SESSION_CACHE_ALIAS</td>
          <td class="code"><pre>&#x27;default&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>SESSION_COOKIE_AGE</td>
          <td class="code"><pre>1209600</pre></td>
        </tr>
      
        <tr>
          <td>SESSION_COOKIE_DOMAIN</td>
          <td class="code"><pre>None</pre></td>
        </tr>
      
        <tr>
          <td>SESSION_COOKIE_HTTPONLY</td>
          <td class="code"><pre>True</pre></td>
        </tr>
      
        <tr>
          <td>SESSION_COOKIE_NAME</td>
          <td class="code"><pre>&#x27;sessionid&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>SESSION_COOKIE_PATH</td>
          <td class="code"><pre>&#x27;/&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>SESSION_COOKIE_SAMESITE</td>
          <td class="code"><pre>&#x27;Lax&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>SESSION_COOKIE_SECURE</td>
          <td class="code"><pre>False</pre></td>
        </tr>
      
        <tr>
          <td>SESSION_ENGINE</td>
          <td class="code"><pre>&#x27;django.contrib.sessions.backends.db&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>SESSION_EXPIRE_AT_BROWSER_CLOSE</td>
          <td class="code"><pre>False</pre></td>
        </tr>
      
        <tr>
          <td>SESSION_FILE_PATH</td>
          <td class="code"><pre>None</pre></td>
        </tr>
      
        <tr>
          <td>SESSION_SAVE_EVERY_REQUEST</td>
          <td class="code"><pre>False</pre></td>
        </tr>
      
        <tr>
          <td>SESSION_SERIALIZER</td>
          <td class="code"><pre>&#x27;django.contrib.sessions.serializers.JSONSerializer&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>SHORT_DATETIME_FORMAT</td>
          <td class="code"><pre>&#x27;m/d/Y P&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>SHORT_DATE_FORMAT</td>
          <td class="code"><pre>&#x27;m/d/Y&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>SIGNING_BACKEND</td>
          <td class="code"><pre>&#x27;django.core.signing.TimestampSigner&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>SILENCED_SYSTEM_CHECKS</td>
          <td class="code"><pre>[]</pre></td>
        </tr>
      
        <tr>
          <td>STATICFILES_DIRS</td>
          <td class="code"><pre>[]</pre></td>
        </tr>
      
        <tr>
          <td>STATICFILES_FINDERS</td>
          <td class="code"><pre>[&#x27;django.contrib.staticfiles.finders.FileSystemFinder&#x27;,
 &#x27;django.contrib.staticfiles.finders.AppDirectoriesFinder&#x27;]</pre></td>
        </tr>
      
        <tr>
          <td>STATIC_ROOT</td>
          <td class="code"><pre>None</pre></td>
        </tr>
      
        <tr>
          <td>STATIC_URL</td>
          <td class="code"><pre>None</pre></td>
        </tr>
      
        <tr>
          <td>STORAGES</td>
          <td class="code"><pre>{&#x27;default&#x27;: {&#x27;BACKEND&#x27;: &#x27;django.core.files.storage.FileSystemStorage&#x27;},
 &#x27;staticfiles&#x27;: {&#x27;BACKEND&#x27;: &#x27;django.contrib.staticfiles.storage.StaticFilesStorage&#x27;}}</pre></td>
        </tr>
      
        <tr>
          <td>TEMPLATES</td>
          <td class="code"><pre>[]</pre></td>
        </tr>
      
        <tr>
          <td>TEST_NON_SERIALIZED_APPS</td>
          <td class="code"><pre>[]</pre></td>
        </tr>
      
        <tr>
          <td>TEST_RUNNER</td>
          <td class="code"><pre>&#x27;django.test.runner.DiscoverRunner&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>THOUSAND_SEPARATOR</td>
          <td class="code"><pre>&#x27;,&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>TIME_FORMAT</td>
          <td class="code"><pre>&#x27;P&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>TIME_INPUT_FORMATS</td>
          <td class="code"><pre>[&#x27;%H:%M:%S&#x27;, &#x27;%H:%M:%S.%f&#x27;, &#x27;%H:%M&#x27;]</pre></td>
        </tr>
      
        <tr>
          <td>TIME_ZONE</td>
          <td class="code"><pre>&#x27;America/Chicago&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>USE_I18N</td>
          <td class="code"><pre>True</pre></td>
        </tr>
      
        <tr>
          <td>USE_THOUSAND_SEPARATOR</td>
          <td class="code"><pre>False</pre></td>
        </tr>
      
        <tr>
          <td>USE_TZ</td>
          <td class="code"><pre>True</pre></td>
        </tr>
      
        <tr>
          <td>USE_X_FORWARDED_HOST</td>
          <td class="code"><pre>False</pre></td>
        </tr>
      
        <tr>
          <td>USE_X_FORWARDED_PORT</td>
          <td class="code"><pre>False</pre></td>
        </tr>
      
        <tr>
          <td>WSGI_APPLICATION</td>
          <td class="code"><pre>None</pre></td>
        </tr>
      
        <tr>
          <td>X_FRAME_OPTIONS</td>
          <td class="code"><pre>&#x27;DENY&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>YEAR_MONTH_FORMAT</td>
          <td class="code"><pre>&#x27;F Y&#x27;</pre></td>
        </tr>
      
    </tbody>
  </table>

</div>
</main>


  <footer id="explanation">
    <p>
      You’re seeing this error because you have <code>DEBUG = True</code> in your
      Django settings file. Change that to <code>False</code>, and Django will
      display a standard page generated by the handler for this status code.
    </p>
  </footer>

</body>
</html>

In this example we add error handling defined as division_error to patch endpoint (which serves as a division operation), while keeping post endpoint (which serves as a multiply operation) without a custom error handler. Because ZeroDivisionError can’t happen in post.

Per-endpoint’s error handling has a priority over per-controller and global handlers.

You can also define endpoint error handlers as controller methods and pass them wrapped with wrap_handler() as handlers. Like so:

Run result

$ curl http://127.0.0.1:8000/api/math/ -D - -X PATCH -d '{"left": 1, "right": 0}' -H 'Content-Type: application/json'
HTTP/1.1 400 Bad Request
date: Tue, 14 Apr 2026 17:08:27 GMT
server: uvicorn
Content-Type: application/json
X-Frame-Options: DENY
Vary: Accept-Language
Content-Language: en
Content-Length: 39
X-Content-Type-Options: nosniff
Referrer-Policy: same-origin
Cross-Origin-Opener-Policy: same-origin

{"detail":[{"msg":"division by zero"}]}

Customizing controller error handler

Let’s create custom error handling for the whole controller:

In this example we are using zapros HTTP client to proxy an HTTP GET and POST requests to some other API service. If we fail to send a request and raise a specific HTTP client error, we return an error with 424 error code.

Going further

Now you can understand how you can create:

  • Endpoints with custom error handlers

  • Controllers with custom error handlers

  • ResponseSpec objects for new error response schemas

You can dive even deeper and:

Error handling diagram

The same error handling logic can be represented as a diagram:

        ---
config:
  theme: forest

---
graph TB
    Start[Request] --> Error{Error?};
    Error -->|Yes| Endpoint[Endpoint-level handler];
    Endpoint --> EndpointHandler{Raises or returns response?};
    EndpointHandler -->|response| Failure[Error response];
    EndpointHandler -->|raises| Controller[Controller-level handler];
    Controller --> ControllerHandler{Raises or returns response?};
    ControllerHandler -->|response| Failure[Error response];
    ControllerHandler -->|raises| Global[Global handler];
    Global --> GlobalHandler{Raises or returns response?};
    GlobalHandler -->|response| Failure[Error response];
    GlobalHandler -->|raises| Reraises[Reraises error];
    Error ---->|No| Success[Successful response];
    

Error handling logic

Note

If Handling 500 errors is configured, it will catch all unhandled errors in the provided scope and return 500 errors with the correct payload.

Customizing error messages

All error messages, including pre-defined ones, can be easily customized on a per-controller basis.

To do so, you would need to change:

  1. error_model attribute for all controllers that will be using this error message schema

  2. format_error() method to provide custom runtime error formatting

Run result

$ curl http://127.0.0.1:8000/api/example/ -X POST -d '{}' -H 'Content-Type: application/json'
{"errors":[{"message":"test msg"}]}

$ curl http://127.0.0.1:8000/api/example/ -X POST -d '[]' -H 'Content-Type: application/json'
{"errors":[{"message":"Input should be a valid dictionary"}]}

OpenAPI Schema

Preview openapi.json
{
  "components": {
    "schemas": {
      "CustomErrorDetail": {
        "properties": {
          "message": {
            "title": "Message",
            "type": "string"
          }
        },
        "required": [
          "message"
        ],
        "title": "CustomErrorDetail",
        "type": "object"
      },
      "CustomErrorModel": {
        "properties": {
          "errors": {
            "items": {
              "$ref": "#/components/schemas/CustomErrorDetail"
            },
            "title": "Errors",
            "type": "array"
          }
        },
        "required": [
          "errors"
        ],
        "title": "CustomErrorModel",
        "type": "object"
      }
    },
    "securitySchemes": {}
  },
  "info": {
    "title": "Django Modern Rest",
    "version": "0.1.0"
  },
  "openapi": "3.2.0",
  "paths": {
    "/api/apicontroller/": {
      "post": {
        "deprecated": false,
        "operationId": "postApicontrollerApiApicontroller",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "additionalProperties": {
                  "type": "string"
                },
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "description": "Created"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CustomErrorModel"
                }
              }
            },
            "description": "Raised when request components cannot be parsed"
          },
          "402": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CustomErrorModel"
                }
              }
            },
            "description": "Payment Required"
          },
          "406": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CustomErrorModel"
                }
              }
            },
            "description": "Raised when provided `Accept` header cannot be satisfied"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CustomErrorModel"
                }
              }
            },
            "description": "Raised when returned response does not match the response schema"
          }
        }
      }
    }
  }
}

This will also change the OpenAPI schema for the affected controller.

See ErrorModel for the default error model schema. And format_error() for the default error formatting.

See content negotiation docs about how to use different error models for different content types.

Customizing error headers and cookies

Let’s say you want to customize how all errors responses behave and add a header, for example, X-Error-Id from your error tracking system.

How this can be done?

Run result

$ curl http://127.0.0.1:8000/api/example/ -X POST -d '{"key": "value"}' -H 'Content-Type: application/json'
{"key":"value"}

$ curl http://127.0.0.1:8000/api/example/ -D - -X POST -d '[]' -H 'Content-Type: application/json'
HTTP/1.1 400 Bad Request
date: Tue, 14 Apr 2026 17:08:29 GMT
server: uvicorn
X-Error-Id: Error-Id from your provider
Content-Type: application/json
X-Frame-Options: DENY
Vary: Accept-Language
Content-Language: en
Content-Length: 100
X-Content-Type-Options: nosniff
Referrer-Policy: same-origin
Cross-Origin-Opener-Policy: same-origin

{"detail":[{"msg":"Input should be a valid dictionary","loc":["parsed_body"],"type":"value_error"}]}

OpenAPI Schema

Preview openapi.json
{
  "components": {
    "schemas": {
      "ErrorDetail": {
        "description": "Base schema for error details description.",
        "properties": {
          "loc": {
            "items": {
              "anyOf": [
                {
                  "type": "integer"
                },
                {
                  "type": "string"
                }
              ]
            },
            "title": "Loc",
            "type": "array"
          },
          "msg": {
            "title": "Msg",
            "type": "string"
          },
          "type": {
            "title": "Type",
            "type": "string"
          }
        },
        "required": [
          "msg"
        ],
        "title": "ErrorDetail",
        "type": "object"
      },
      "ErrorModel": {
        "description": "Default error response schema.\n\nCan be customized.\nSee :ref:`customizing-error-messages` for more details.",
        "properties": {
          "detail": {
            "items": {
              "$ref": "#/components/schemas/ErrorDetail"
            },
            "title": "Detail",
            "type": "array"
          }
        },
        "required": [
          "detail"
        ],
        "title": "ErrorModel",
        "type": "object"
      }
    },
    "securitySchemes": {}
  },
  "info": {
    "title": "Django Modern Rest",
    "version": "0.1.0"
  },
  "openapi": "3.2.0",
  "paths": {
    "/api/apicontroller/": {
      "post": {
        "deprecated": false,
        "operationId": "postApicontrollerApiApicontroller",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "additionalProperties": {
                  "type": "string"
                },
                "type": "object"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "additionalProperties": {
                    "type": "string"
                  },
                  "type": "object"
                }
              }
            },
            "description": "Created"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Raised when request components cannot be parsed",
            "headers": {
              "X-Error-Id": {
                "required": true,
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "406": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Raised when provided `Accept` header cannot be satisfied",
            "headers": {
              "X-Error-Id": {
                "required": true,
                "schema": {
                  "type": "string"
                }
              }
            }
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Raised when returned response does not match the response schema",
            "headers": {
              "X-Error-Id": {
                "required": true,
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    }
  }
}

To attach response headers or cookies to the error model we use ResponseSpecMetadata inside typing.Annotated type.

We also have to redefine to_error() to add missing X-Error-Id headers for your error responses.

You can do the same for all responses, not just failing ones. For this, override to_response().

This can also be used to attach RateLimit headers and other Throttling information.

Problem Details

django-modern-rest supports customizing of all error message inside the framework, including builtin ones.

ProblemDetailsError is a great example of how it can be done.

It is a regular subclass of APIError, which does not have any special handling inside our framework. This is done on purpose, so we can be sure that users also can to customize their exceptions any way they need.

We support two main use-cases for Problem Details.

Always raising Problem Details

To always use ProblemDetailsError inside your controller you would need to:

  1. Define error_model attribute as ProblemDetailsModel

  2. Raise an exception itself, pass all the required fields

  3. Convert other message to the Problem Details format using format_error() method

Run result

$ curl http://127.0.0.1:8000/api/balance/ -X GET
{"detail":"Your current balance is 0, but the price is 15","status":402,"type":"https://example.com/probs/out-of-credit","title":"Not enough funds","instance":"/account/users/1/","balance":0,"price":15}

$ curl 'http://127.0.0.1:8000/api/balance/?number=a' -X GET
{"detail":"Input should be a valid integer, unable to parse string as an integer","status":400,"type":"value_error","title":"From format_error"}

OpenAPI Schema

Preview openapi.json
{
  "components": {
    "schemas": {
      "ProblemDetailsModel": {
        "description": "Error payload model for Problem Details.\n\nSee https://datatracker.ietf.org/doc/html/rfc9457\nfor the detailed description of each field.",
        "properties": {
          "detail": {
            "title": "Detail",
            "type": "string"
          },
          "instance": {
            "title": "Instance",
            "type": "string"
          },
          "status": {
            "title": "Status",
            "type": "integer"
          },
          "title": {
            "title": "Title",
            "type": "string"
          },
          "type": {
            "title": "Type",
            "type": "string"
          }
        },
        "title": "ProblemDetailsModel",
        "type": "object"
      }
    },
    "securitySchemes": {}
  },
  "info": {
    "title": "Django Modern Rest",
    "version": "0.1.0"
  },
  "openapi": "3.2.0",
  "paths": {
    "/api/problemdetailscontroller/": {
      "get": {
        "deprecated": false,
        "operationId": "getProblemdetailscontrollerApiProblemdetailscontroller",
        "parameters": [
          {
            "deprecated": false,
            "in": "query",
            "name": "number",
            "schema": {
              "default": 0,
              "title": "Number",
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "description": "OK"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetailsModel"
                }
              }
            },
            "description": "Raised when request components cannot be parsed"
          },
          "402": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetailsModel"
                }
              }
            },
            "description": "Payment Required"
          },
          "406": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetailsModel"
                }
              }
            },
            "description": "Raised when provided `Accept` header cannot be satisfied"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetailsModel"
                }
              }
            },
            "description": "Raised when returned response does not match the response schema"
          }
        }
      }
    }
  }
}

Conditionally raising Problem Details

Another way is to negotiate the error response format. How does it work?

  1. When user sends a request with Accept header with application/problem+json content type, we will return Problem Details errors

  2. When application/json or any other content type is sent, we return regular ErrorModel error payloads

To do so, you would need a slightly more difficult setup:

  1. Define error_model attribute as the result of error_model() method call. It will add conditional schema types to your error responses

  2. Define several Renderer types, including the one which will handle application/problem+json

  3. Raise a conditional exception: use conditional_error() to only raise Problem Details when the correct accepted type is passed

  4. Convert other message to the Problem Details format using format_error() method when the correct accepted type is passed

Run result

$ curl http://127.0.0.1:8000/api/balance/ -X GET
{"detail":[{"msg":"Your current balance is 0, but the price is 15","type":"https://example.com/probs/out-of-credit"}]}

$ curl http://127.0.0.1:8000/api/balance/ -X GET -H 'Accept: application/problem+json'
{"detail":"Your current balance is 0, but the price is 15","status":402,"type":"https://example.com/probs/out-of-credit","title":"Not enough funds","instance":"/account/users/1/","balance":0,"price":15}

OpenAPI Schema

Preview openapi.json
{
  "components": {
    "schemas": {
      "ErrorDetail": {
        "description": "Base schema for error details description.",
        "properties": {
          "loc": {
            "items": {
              "anyOf": [
                {
                  "type": "integer"
                },
                {
                  "type": "string"
                }
              ]
            },
            "title": "Loc",
            "type": "array"
          },
          "msg": {
            "title": "Msg",
            "type": "string"
          },
          "type": {
            "title": "Type",
            "type": "string"
          }
        },
        "required": [
          "msg"
        ],
        "title": "ErrorDetail",
        "type": "object"
      },
      "ErrorModel": {
        "description": "Default error response schema.\n\nCan be customized.\nSee :ref:`customizing-error-messages` for more details.",
        "properties": {
          "detail": {
            "items": {
              "$ref": "#/components/schemas/ErrorDetail"
            },
            "title": "Detail",
            "type": "array"
          }
        },
        "required": [
          "detail"
        ],
        "title": "ErrorModel",
        "type": "object"
      },
      "ProblemDetailsModel": {
        "description": "Error payload model for Problem Details.\n\nSee https://datatracker.ietf.org/doc/html/rfc9457\nfor the detailed description of each field.",
        "properties": {
          "detail": {
            "title": "Detail",
            "type": "string"
          },
          "instance": {
            "title": "Instance",
            "type": "string"
          },
          "status": {
            "title": "Status",
            "type": "integer"
          },
          "title": {
            "title": "Title",
            "type": "string"
          },
          "type": {
            "title": "Type",
            "type": "string"
          }
        },
        "title": "ProblemDetailsModel",
        "type": "object"
      }
    },
    "securitySchemes": {}
  },
  "info": {
    "title": "Django Modern Rest",
    "version": "0.1.0"
  },
  "openapi": "3.2.0",
  "paths": {
    "/api/problemdetailscontroller/": {
      "get": {
        "deprecated": false,
        "operationId": "getProblemdetailscontrollerApiProblemdetailscontroller",
        "responses": {
          "200": {
            "content": {
              "application/json": {
                "schema": {
                  "type": "string"
                }
              },
              "application/problem+json": {
                "schema": {
                  "type": "string"
                }
              }
            },
            "description": "OK"
          },
          "402": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetailsModel"
                }
              }
            },
            "description": "Payment Required"
          },
          "406": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetailsModel"
                }
              }
            },
            "description": "Raised when provided `Accept` header cannot be satisfied"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              },
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetailsModel"
                }
              }
            },
            "description": "Raised when returned response does not match the response schema"
          }
        }
      }
    }
  }
}

Tip

You can still make application/problem+json the default and when application/json (or any other type) is explicitly requested return the ErrorModel errors.

Handling validation errors from models

When creating models with, for example, pydantic.BaseModel, your validation can fail. This error will not be handled by design.

Why? Because catching all specific validation errors for a specific serializer that can happen in your application will do more harm than good.

This is the default behavior:

Run result

$ curl http://127.0.0.1:8000/api/ping/ -D - -X GET
HTTP/1.1 500 Internal Server Error
date: Tue, 14 Apr 2026 17:08:31 GMT
server: uvicorn
Content-Type: text/html; charset=utf-8
X-Frame-Options: DENY
Vary: Accept-Language, Cookie
Content-Language: en
Content-Length: 97687
X-Content-Type-Options: nosniff
Referrer-Policy: same-origin
Cross-Origin-Opener-Policy: same-origin

<!DOCTYPE html>
<html lang="en">
<head>
  <meta http-equiv="content-type" content="text/html; charset=utf-8">
  <meta name="robots" content="NONE,NOARCHIVE">
  <title>ValidationError
          at /api/ping/</title>
  <style>
    html * { padding:0; margin:0; }
    body * { padding:10px 20px; }
    body * * { padding:0; }
    body { font-family: sans-serif; background-color:#fff; color:#000; }
    body > :where(header, main, footer) { border-bottom:1px solid #ddd; }
    h1 { font-weight:normal; }
    h2 { margin-bottom:.8em; }
    h3 { margin:1em 0 .5em 0; }
    h4 { margin:0 0 .5em 0; font-weight: normal; }
    code, pre { font-size: 100%; white-space: pre-wrap; word-break: break-word; }
    summary { cursor: pointer; }
    table { border:1px solid #ccc; border-collapse: collapse; width:100%; background:white; }
    tbody td, tbody th { vertical-align:top; padding:2px 3px; }
    thead th {
      padding:1px 6px 1px 3px; background:#fefefe; text-align:left;
      font-weight:normal; font-size: 0.6875rem; border:1px solid #ddd;
    }
    tbody th { width:12em; text-align:right; color:#666; padding-right:.5em; }
    table.vars { margin:5px 10px 2px 40px; width: auto; }
    table.vars td, table.req td { font-family:monospace; }
    table td.code { width:100%; }
    table td.code pre { overflow:hidden; }
    table.source th { color:#666; }
    table.source td { font-family:monospace; white-space:pre; border-bottom:1px solid #eee; }
    ul.traceback { list-style-type:none; color: #222; }
    ul.traceback li.cause { word-break: break-word; }
    ul.traceback li.frame { padding-bottom:1em; color:#4f4f4f; }
    ul.traceback li.user { background-color:#e0e0e0; color:#000 }
    div.context { padding:10px 0; overflow:hidden; }
    div.context ol { padding-left:30px; margin:0 10px; list-style-position: inside; }
    div.context ol li { font-family:monospace; white-space:pre; color:#777; cursor:pointer; padding-left: 2px; }
    div.context ol li pre { display:inline; }
    div.context ol.context-line li { color:#464646; background-color:#dfdfdf; padding: 3px 2px; }
    div.context ol.context-line li span { position:absolute; right:32px; }
    .user div.context ol.context-line li { background-color:#bbb; color:#000; }
    .user div.context ol li { color:#666; }
    div.commands, summary.commands { margin-left: 40px; }
    div.commands a, summary.commands { color:#555; text-decoration:none; }
    .user div.commands a { color: black; }
    #summary { background: #ffc; }
    #summary h2 { font-weight: normal; color: #666; }
    #info { padding: 0; }
    #info > * { padding:10px 20px; }
    #explanation { background:#eee; }
    #template, #template-not-exist { background:#f6f6f6; }
    #template-not-exist ul { margin: 0 0 10px 20px; }
    #template-not-exist .postmortem-section { margin-bottom: 3px; }
    #unicode-hint { background:#eee; }
    #traceback { background:#eee; }
    #requestinfo { background:#f6f6f6; padding-left:120px; }
    #summary table { border:none; background:transparent; }
    #requestinfo h2, #requestinfo h3 { position:relative; margin-left:-100px; }
    #requestinfo h3 { margin-bottom:-1em; }
    .error { background: #ffc; }
    .specific { color:#cc3300; font-weight:bold; }
    h2 span.commands { font-size: 0.7rem; font-weight:normal; }
    span.commands a:link {color:#5E5694;}
    pre.exception_value { font-family: sans-serif; color: #575757; font-size: 1.5rem; margin: 10px 0 10px 0; }
    .append-bottom { margin-bottom: 10px; }
    .fname { user-select: all; }
  </style>
  
  <script>
    function hideAll(elems) {
      for (var e = 0; e < elems.length; e++) {
        elems[e].style.display = 'none';
      }
    }
    window.onload = function() {
      hideAll(document.querySelectorAll('ol.pre-context'));
      hideAll(document.querySelectorAll('ol.post-context'));
      hideAll(document.querySelectorAll('div.pastebin'));
    }
    function toggle() {
      for (var i = 0; i < arguments.length; i++) {
        var e = document.getElementById(arguments[i]);
        if (e) {
          e.style.display = e.style.display == 'none' ? 'block': 'none';
        }
      }
      return false;
    }
    function switchPastebinFriendly(link) {
      s1 = "Switch to copy-and-paste view";
      s2 = "Switch back to interactive view";
      link.textContent = link.textContent.trim() == s1 ? s2: s1;
      toggle('browserTraceback', 'pastebinTraceback');
      return false;
    }
  </script>
  
</head>
<body>
<header id="summary">
  <h1>ValidationError
       at /api/ping/</h1>
  <pre class="exception_value">1 validation error for Pong
message
  Input should be &#x27;pong&#x27; [type=literal_error, input_value=&#x27;wrong&#x27;, input_type=str]
    For further information visit https://errors.pydantic.dev/2.13/v/literal_error</pre>
  <table class="meta">

    <tr>
      <th scope="row">Request Method:</th>
      <td>GET</td>
    </tr>
    <tr>
      <th scope="row">Request URL:</th>
      <td>http://127.0.0.1:58663/api/ping/</td>
    </tr>

    <tr>
      <th scope="row">Django Version:</th>
      <td>5.2.13</td>
    </tr>

    <tr>
      <th scope="row">Exception Type:</th>
      <td>ValidationError</td>
    </tr>


    <tr>
      <th scope="row">Exception Value:</th>
      <td><pre>1 validation error for Pong
message
  Input should be &#x27;pong&#x27; [type=literal_error, input_value=&#x27;wrong&#x27;, input_type=str]
    For further information visit https://errors.pydantic.dev/2.13/v/literal_error</pre></td>
    </tr>


    <tr>
      <th scope="row">Exception Location:</th>
      <td><span class="fname">/home/docs/checkouts/readthedocs.org/user_builds/django-modern-rest/envs/0.7.0/lib/python3.12/site-packages/pydantic/main.py</span>, line 263, in __init__</td>
    </tr>


    <tr>
      <th scope="row">Raised during:</th>
      <td>examples.error_handling.pydantic_validation_error.PongController</td>
    </tr>

    <tr>
      <th scope="row">Python Executable:</th>
      <td>/home/docs/checkouts/readthedocs.org/user_builds/django-modern-rest/envs/0.7.0/bin/python</td>
    </tr>
    <tr>
      <th scope="row">Python Version:</th>
      <td>3.12.10</td>
    </tr>
    <tr>
      <th scope="row">Python Path:</th>
      <td><pre><code>[&#x27;/home/docs/checkouts/readthedocs.org/user_builds/django-modern-rest/checkouts/0.7.0&#x27;,
 &#x27;/home/docs/checkouts/readthedocs.org/user_builds/django-modern-rest/checkouts/0.7.0/django_test_app&#x27;,
 &#x27;/home/docs/checkouts/readthedocs.org/user_builds/django-modern-rest/checkouts/0.7.0/docs&#x27;,
 &#x27;/home/docs/.asdf/installs/python/3.12.10/lib/python312.zip&#x27;,
 &#x27;/home/docs/.asdf/installs/python/3.12.10/lib/python3.12&#x27;,
 &#x27;/home/docs/.asdf/installs/python/3.12.10/lib/python3.12/lib-dynload&#x27;,
 &#x27;/home/docs/checkouts/readthedocs.org/user_builds/django-modern-rest/envs/0.7.0/lib/python3.12/site-packages&#x27;]</code></pre></td>
    </tr>
    <tr>
      <th scope="row">Server time:</th>
      <td>Tue, 14 Apr 2026 12:08:31 -0500</td>
    </tr>
  </table>
</header>

<main id="info">




<div id="traceback">
  <h2>Traceback <span class="commands"><a href="#" role="button" onclick="return switchPastebinFriendly(this);">
    Switch to copy-and-paste view</a></span>
  </h2>
  <div id="browserTraceback">
    <ul class="traceback">
      
        
        <li class="frame django">
          
            <code class="fname">/home/docs/checkouts/readthedocs.org/user_builds/django-modern-rest/envs/0.7.0/lib/python3.12/site-packages/django/core/handlers/exception.py</code>, line 42, in inner
          

          
            <div class="context" id="c140501913202368">
              
                <ol start="35" class="pre-context" id="pre140501913202368">
                
                  <li onclick="toggle('pre140501913202368', 'post140501913202368')"><pre>    can rely on getting a response instead of an exception.</pre></li>
                
                  <li onclick="toggle('pre140501913202368', 'post140501913202368')"><pre>    &quot;&quot;&quot;</pre></li>
                
                  <li onclick="toggle('pre140501913202368', 'post140501913202368')"><pre>    if iscoroutinefunction(get_response):</pre></li>
                
                  <li onclick="toggle('pre140501913202368', 'post140501913202368')"><pre></pre></li>
                
                  <li onclick="toggle('pre140501913202368', 'post140501913202368')"><pre>        @wraps(get_response)</pre></li>
                
                  <li onclick="toggle('pre140501913202368', 'post140501913202368')"><pre>        async def inner(request):</pre></li>
                
                  <li onclick="toggle('pre140501913202368', 'post140501913202368')"><pre>            try:</pre></li>
                
                </ol>
              
              <ol start="42" class="context-line">
                <li onclick="toggle('pre140501913202368', 'post140501913202368')"><pre>                response = await get_response(request)
                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^</pre> <span>…</span></li>
              </ol>
              
                <ol start='43' class="post-context" id="post140501913202368">
                  
                  <li onclick="toggle('pre140501913202368', 'post140501913202368')"><pre>            except Exception as exc:</pre></li>
                  
                  <li onclick="toggle('pre140501913202368', 'post140501913202368')"><pre>                response = await sync_to_async(</pre></li>
                  
                  <li onclick="toggle('pre140501913202368', 'post140501913202368')"><pre>                    response_for_exception, thread_sensitive=False</pre></li>
                  
                  <li onclick="toggle('pre140501913202368', 'post140501913202368')"><pre>                )(request, exc)</pre></li>
                  
                  <li onclick="toggle('pre140501913202368', 'post140501913202368')"><pre>            return response</pre></li>
                  
                  <li onclick="toggle('pre140501913202368', 'post140501913202368')"><pre></pre></li>
                  
              </ol>
              
            </div>
          

          
            
              <details>
                <summary class="commands">Local vars</summary>
            
            <table class="vars" id="v140501913202368">
              <thead>
                <tr>
                  <th scope="col">Variable</th>
                  <th scope="col">Value</th>
                </tr>
              </thead>
              <tbody>
                
                  <tr>
                    <td>exc</td>
                    <td class="code"><pre>1 validation error for Pong
message
  Input should be &#x27;pong&#x27; [type=literal_error, input_value=&#x27;wrong&#x27;, input_type=str]
    For further information visit https://errors.pydantic.dev/2.13/v/literal_error</pre></td>
                  </tr>
                
                  <tr>
                    <td>get_response</td>
                    <td class="code"><pre>&lt;bound method BaseHandler._get_response_async of &lt;django.core.handlers.asgi.ASGIHandler object at 0x7fc926ea0500&gt;&gt;</pre></td>
                  </tr>
                
                  <tr>
                    <td>request</td>
                    <td class="code"><pre>&lt;ASGIRequest: GET &#x27;/api/ping/&#x27;&gt;</pre></td>
                  </tr>
                
              </tbody>
            </table>
            </details>
          
        </li>
      
        
        <li class="frame django">
          
            <code class="fname">/home/docs/checkouts/readthedocs.org/user_builds/django-modern-rest/envs/0.7.0/lib/python3.12/site-packages/django/core/handlers/base.py</code>, line 253, in _get_response_async
          

          
            <div class="context" id="c140501913179136">
              
                <ol start="246" class="pre-context" id="pre140501913179136">
                
                  <li onclick="toggle('pre140501913179136', 'post140501913179136')"><pre>            wrapped_callback = self.make_view_atomic(callback)</pre></li>
                
                  <li onclick="toggle('pre140501913179136', 'post140501913179136')"><pre>            # If it is a synchronous view, run it in a subthread</pre></li>
                
                  <li onclick="toggle('pre140501913179136', 'post140501913179136')"><pre>            if not iscoroutinefunction(wrapped_callback):</pre></li>
                
                  <li onclick="toggle('pre140501913179136', 'post140501913179136')"><pre>                wrapped_callback = sync_to_async(</pre></li>
                
                  <li onclick="toggle('pre140501913179136', 'post140501913179136')"><pre>                    wrapped_callback, thread_sensitive=True</pre></li>
                
                  <li onclick="toggle('pre140501913179136', 'post140501913179136')"><pre>                )</pre></li>
                
                  <li onclick="toggle('pre140501913179136', 'post140501913179136')"><pre>            try:</pre></li>
                
                </ol>
              
              <ol start="253" class="context-line">
                <li onclick="toggle('pre140501913179136', 'post140501913179136')"><pre>                response = await wrapped_callback(
                                </pre> <span>…</span></li>
              </ol>
              
                <ol start='254' class="post-context" id="post140501913179136">
                  
                  <li onclick="toggle('pre140501913179136', 'post140501913179136')"><pre>                    request, *callback_args, **callback_kwargs</pre></li>
                  
                  <li onclick="toggle('pre140501913179136', 'post140501913179136')"><pre>                )</pre></li>
                  
                  <li onclick="toggle('pre140501913179136', 'post140501913179136')"><pre>            except Exception as e:</pre></li>
                  
                  <li onclick="toggle('pre140501913179136', 'post140501913179136')"><pre>                response = await sync_to_async(</pre></li>
                  
                  <li onclick="toggle('pre140501913179136', 'post140501913179136')"><pre>                    self.process_exception_by_middleware,</pre></li>
                  
                  <li onclick="toggle('pre140501913179136', 'post140501913179136')"><pre>                    thread_sensitive=True,</pre></li>
                  
              </ol>
              
            </div>
          

          
            
              <details>
                <summary class="commands">Local vars</summary>
            
            <table class="vars" id="v140501913179136">
              <thead>
                <tr>
                  <th scope="col">Variable</th>
                  <th scope="col">Value</th>
                </tr>
              </thead>
              <tbody>
                
                  <tr>
                    <td>callback</td>
                    <td class="code"><pre>&lt;function View.as_view.&lt;locals&gt;.view at 0x7fc926dd9300&gt;</pre></td>
                  </tr>
                
                  <tr>
                    <td>callback_args</td>
                    <td class="code"><pre>()</pre></td>
                  </tr>
                
                  <tr>
                    <td>callback_kwargs</td>
                    <td class="code"><pre>{}</pre></td>
                  </tr>
                
                  <tr>
                    <td>middleware_method</td>
                    <td class="code"><pre>&lt;asgiref.sync.SyncToAsync object at 0x7fc926ec1b50&gt;</pre></td>
                  </tr>
                
                  <tr>
                    <td>request</td>
                    <td class="code"><pre>&lt;ASGIRequest: GET &#x27;/api/ping/&#x27;&gt;</pre></td>
                  </tr>
                
                  <tr>
                    <td>response</td>
                    <td class="code"><pre>None</pre></td>
                  </tr>
                
                  <tr>
                    <td>self</td>
                    <td class="code"><pre>&lt;django.core.handlers.asgi.ASGIHandler object at 0x7fc926ea0500&gt;</pre></td>
                  </tr>
                
                  <tr>
                    <td>wrapped_callback</td>
                    <td class="code"><pre>&lt;asgiref.sync.SyncToAsync object at 0x7fc926e5ba70&gt;</pre></td>
                  </tr>
                
              </tbody>
            </table>
            </details>
          
        </li>
      
        
        <li class="frame user">
          
            <code class="fname">/home/docs/.asdf/installs/python/3.12.10/lib/python3.12/concurrent/futures/thread.py</code>, line 59, in run
          

          
            <div class="context" id="c140501913197568">
              
                <ol start="52" class="pre-context" id="pre140501913197568">
                
                  <li onclick="toggle('pre140501913197568', 'post140501913197568')"><pre>        self.kwargs = kwargs</pre></li>
                
                  <li onclick="toggle('pre140501913197568', 'post140501913197568')"><pre></pre></li>
                
                  <li onclick="toggle('pre140501913197568', 'post140501913197568')"><pre>    def run(self):</pre></li>
                
                  <li onclick="toggle('pre140501913197568', 'post140501913197568')"><pre>        if not self.future.set_running_or_notify_cancel():</pre></li>
                
                  <li onclick="toggle('pre140501913197568', 'post140501913197568')"><pre>            return</pre></li>
                
                  <li onclick="toggle('pre140501913197568', 'post140501913197568')"><pre></pre></li>
                
                  <li onclick="toggle('pre140501913197568', 'post140501913197568')"><pre>        try:</pre></li>
                
                </ol>
              
              <ol start="59" class="context-line">
                <li onclick="toggle('pre140501913197568', 'post140501913197568')"><pre>            result = self.fn(*self.args, **self.kwargs)
                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^</pre> <span>…</span></li>
              </ol>
              
                <ol start='60' class="post-context" id="post140501913197568">
                  
                  <li onclick="toggle('pre140501913197568', 'post140501913197568')"><pre>        except BaseException as exc:</pre></li>
                  
                  <li onclick="toggle('pre140501913197568', 'post140501913197568')"><pre>            self.future.set_exception(exc)</pre></li>
                  
                  <li onclick="toggle('pre140501913197568', 'post140501913197568')"><pre>            # Break a reference cycle with the exception &#x27;exc&#x27;</pre></li>
                  
                  <li onclick="toggle('pre140501913197568', 'post140501913197568')"><pre>            self = None</pre></li>
                  
                  <li onclick="toggle('pre140501913197568', 'post140501913197568')"><pre>        else:</pre></li>
                  
                  <li onclick="toggle('pre140501913197568', 'post140501913197568')"><pre>            self.future.set_result(result)</pre></li>
                  
              </ol>
              
            </div>
          

          
            
              <details>
                <summary class="commands">Local vars</summary>
            
            <table class="vars" id="v140501913197568">
              <thead>
                <tr>
                  <th scope="col">Variable</th>
                  <th scope="col">Value</th>
                </tr>
              </thead>
              <tbody>
                
                  <tr>
                    <td>self</td>
                    <td class="code"><pre>None</pre></td>
                  </tr>
                
              </tbody>
            </table>
            </details>
          
        </li>
      
        
        <li class="frame django">
          
            <code class="fname">/home/docs/checkouts/readthedocs.org/user_builds/django-modern-rest/envs/0.7.0/lib/python3.12/site-packages/django/views/decorators/csrf.py</code>, line 65, in _view_wrapper
          

          
            <div class="context" id="c140501913194048">
              
                <ol start="58" class="pre-context" id="pre140501913194048">
                
                  <li onclick="toggle('pre140501913194048', 'post140501913194048')"><pre></pre></li>
                
                  <li onclick="toggle('pre140501913194048', 'post140501913194048')"><pre>        async def _view_wrapper(request, *args, **kwargs):</pre></li>
                
                  <li onclick="toggle('pre140501913194048', 'post140501913194048')"><pre>            return await view_func(request, *args, **kwargs)</pre></li>
                
                  <li onclick="toggle('pre140501913194048', 'post140501913194048')"><pre></pre></li>
                
                  <li onclick="toggle('pre140501913194048', 'post140501913194048')"><pre>    else:</pre></li>
                
                  <li onclick="toggle('pre140501913194048', 'post140501913194048')"><pre></pre></li>
                
                  <li onclick="toggle('pre140501913194048', 'post140501913194048')"><pre>        def _view_wrapper(request, *args, **kwargs):</pre></li>
                
                </ol>
              
              <ol start="65" class="context-line">
                <li onclick="toggle('pre140501913194048', 'post140501913194048')"><pre>            return view_func(request, *args, **kwargs)
                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^</pre> <span>…</span></li>
              </ol>
              
                <ol start='66' class="post-context" id="post140501913194048">
                  
                  <li onclick="toggle('pre140501913194048', 'post140501913194048')"><pre></pre></li>
                  
                  <li onclick="toggle('pre140501913194048', 'post140501913194048')"><pre>    _view_wrapper.csrf_exempt = True</pre></li>
                  
                  <li onclick="toggle('pre140501913194048', 'post140501913194048')"><pre></pre></li>
                  
                  <li onclick="toggle('pre140501913194048', 'post140501913194048')"><pre>    return wraps(view_func)(_view_wrapper)</pre></li>
                  
              </ol>
              
            </div>
          

          
            
              <details>
                <summary class="commands">Local vars</summary>
            
            <table class="vars" id="v140501913194048">
              <thead>
                <tr>
                  <th scope="col">Variable</th>
                  <th scope="col">Value</th>
                </tr>
              </thead>
              <tbody>
                
                  <tr>
                    <td>args</td>
                    <td class="code"><pre>()</pre></td>
                  </tr>
                
                  <tr>
                    <td>kwargs</td>
                    <td class="code"><pre>{}</pre></td>
                  </tr>
                
                  <tr>
                    <td>request</td>
                    <td class="code"><pre>&lt;ASGIRequest: GET &#x27;/api/ping/&#x27;&gt;</pre></td>
                  </tr>
                
                  <tr>
                    <td>view_func</td>
                    <td class="code"><pre>&lt;function View.as_view.&lt;locals&gt;.view at 0x7fc926ddac00&gt;</pre></td>
                  </tr>
                
              </tbody>
            </table>
            </details>
          
        </li>
      
        
        <li class="frame django">
          
            <code class="fname">/home/docs/checkouts/readthedocs.org/user_builds/django-modern-rest/envs/0.7.0/lib/python3.12/site-packages/django/views/generic/base.py</code>, line 105, in view
          

          
            <div class="context" id="c140501913182208">
              
                <ol start="98" class="pre-context" id="pre140501913182208">
                
                  <li onclick="toggle('pre140501913182208', 'post140501913182208')"><pre>            self = cls(**initkwargs)</pre></li>
                
                  <li onclick="toggle('pre140501913182208', 'post140501913182208')"><pre>            self.setup(request, *args, **kwargs)</pre></li>
                
                  <li onclick="toggle('pre140501913182208', 'post140501913182208')"><pre>            if not hasattr(self, &quot;request&quot;):</pre></li>
                
                  <li onclick="toggle('pre140501913182208', 'post140501913182208')"><pre>                raise AttributeError(</pre></li>
                
                  <li onclick="toggle('pre140501913182208', 'post140501913182208')"><pre>                    &quot;%s instance has no &#x27;request&#x27; attribute. Did you override &quot;</pre></li>
                
                  <li onclick="toggle('pre140501913182208', 'post140501913182208')"><pre>                    &quot;setup() and forget to call super()?&quot; % cls.__name__</pre></li>
                
                  <li onclick="toggle('pre140501913182208', 'post140501913182208')"><pre>                )</pre></li>
                
                </ol>
              
              <ol start="105" class="context-line">
                <li onclick="toggle('pre140501913182208', 'post140501913182208')"><pre>            return self.dispatch(request, *args, **kwargs)
                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^</pre> <span>…</span></li>
              </ol>
              
                <ol start='106' class="post-context" id="post140501913182208">
                  
                  <li onclick="toggle('pre140501913182208', 'post140501913182208')"><pre></pre></li>
                  
                  <li onclick="toggle('pre140501913182208', 'post140501913182208')"><pre>        view.view_class = cls</pre></li>
                  
                  <li onclick="toggle('pre140501913182208', 'post140501913182208')"><pre>        view.view_initkwargs = initkwargs</pre></li>
                  
                  <li onclick="toggle('pre140501913182208', 'post140501913182208')"><pre></pre></li>
                  
                  <li onclick="toggle('pre140501913182208', 'post140501913182208')"><pre>        # __name__ and __qualname__ are intentionally left unchanged as</pre></li>
                  
                  <li onclick="toggle('pre140501913182208', 'post140501913182208')"><pre>        # view_class should be used to robustly determine the name of the view</pre></li>
                  
              </ol>
              
            </div>
          

          
            
              <details>
                <summary class="commands">Local vars</summary>
            
            <table class="vars" id="v140501913182208">
              <thead>
                <tr>
                  <th scope="col">Variable</th>
                  <th scope="col">Value</th>
                </tr>
              </thead>
              <tbody>
                
                  <tr>
                    <td>args</td>
                    <td class="code"><pre>()</pre></td>
                  </tr>
                
                  <tr>
                    <td>cls</td>
                    <td class="code"><pre>&lt;class &#x27;examples.error_handling.pydantic_validation_error.PongController&#x27;&gt;</pre></td>
                  </tr>
                
                  <tr>
                    <td>initkwargs</td>
                    <td class="code"><pre>{}</pre></td>
                  </tr>
                
                  <tr>
                    <td>kwargs</td>
                    <td class="code"><pre>{}</pre></td>
                  </tr>
                
                  <tr>
                    <td>request</td>
                    <td class="code"><pre>&lt;ASGIRequest: GET &#x27;/api/ping/&#x27;&gt;</pre></td>
                  </tr>
                
                  <tr>
                    <td>self</td>
                    <td class="code"><pre>&lt;examples.error_handling.pydantic_validation_error.PongController object at 0x7fc926e5a7b0&gt;</pre></td>
                  </tr>
                
              </tbody>
            </table>
            </details>
          
        </li>
      
        
        <li class="frame user">
          
            <code class="fname">/home/docs/checkouts/readthedocs.org/user_builds/django-modern-rest/checkouts/0.7.0/dmr/controller.py</code>, line 241, in dispatch
          

          
            <div class="context" id="c140501913193792">
              
                <ol start="234" class="pre-context" id="pre140501913193792">
                
                  <li onclick="toggle('pre140501913193792', 'post140501913193792')"><pre></pre></li>
                
                  <li onclick="toggle('pre140501913193792', 'post140501913193792')"><pre>        Return 405 if this method is not allowed.</pre></li>
                
                  <li onclick="toggle('pre140501913193792', 'post140501913193792')"><pre>        &quot;&quot;&quot;</pre></li>
                
                  <li onclick="toggle('pre140501913193792', 'post140501913193792')"><pre>        # Fast path for method resolution:</pre></li>
                
                  <li onclick="toggle('pre140501913193792', 'post140501913193792')"><pre>        method: str = request.method  # type: ignore[assignment]</pre></li>
                
                  <li onclick="toggle('pre140501913193792', 'post140501913193792')"><pre>        endpoint = self.api_endpoints.get(method)</pre></li>
                
                  <li onclick="toggle('pre140501913193792', 'post140501913193792')"><pre>        if endpoint is not None:</pre></li>
                
                </ol>
              
              <ol start="241" class="context-line">
                <li onclick="toggle('pre140501913193792', 'post140501913193792')"><pre>            return endpoint(self, *args, **kwargs)
                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^</pre> <span>…</span></li>
              </ol>
              
                <ol start='242' class="post-context" id="post140501913193792">
                  
                  <li onclick="toggle('pre140501913193792', 'post140501913193792')"><pre>        # This return is very special,</pre></li>
                  
                  <li onclick="toggle('pre140501913193792', 'post140501913193792')"><pre>        # since it does not have an attached endpoint.</pre></li>
                  
                  <li onclick="toggle('pre140501913193792', 'post140501913193792')"><pre>        # All other responses are handled on endpoint level</pre></li>
                  
                  <li onclick="toggle('pre140501913193792', 'post140501913193792')"><pre>        # with all the response type validation.</pre></li>
                  
                  <li onclick="toggle('pre140501913193792', 'post140501913193792')"><pre>        return self.handle_method_not_allowed(method)</pre></li>
                  
                  <li onclick="toggle('pre140501913193792', 'post140501913193792')"><pre></pre></li>
                  
              </ol>
              
            </div>
          

          
            
              <details>
                <summary class="commands">Local vars</summary>
            
            <table class="vars" id="v140501913193792">
              <thead>
                <tr>
                  <th scope="col">Variable</th>
                  <th scope="col">Value</th>
                </tr>
              </thead>
              <tbody>
                
                  <tr>
                    <td>args</td>
                    <td class="code"><pre>()</pre></td>
                  </tr>
                
                  <tr>
                    <td>endpoint</td>
                    <td class="code"><pre>&lt;dmr.endpoint.Endpoint object at 0x7fc926dc93f0&gt;</pre></td>
                  </tr>
                
                  <tr>
                    <td>kwargs</td>
                    <td class="code"><pre>{}</pre></td>
                  </tr>
                
                  <tr>
                    <td>method</td>
                    <td class="code"><pre>&#x27;GET&#x27;</pre></td>
                  </tr>
                
                  <tr>
                    <td>request</td>
                    <td class="code"><pre>&lt;ASGIRequest: GET &#x27;/api/ping/&#x27;&gt;</pre></td>
                  </tr>
                
                  <tr>
                    <td>self</td>
                    <td class="code"><pre>&lt;examples.error_handling.pydantic_validation_error.PongController object at 0x7fc926e5a7b0&gt;</pre></td>
                  </tr>
                
              </tbody>
            </table>
            </details>
          
        </li>
      
        
        <li class="frame user">
          
            <code class="fname">/home/docs/checkouts/readthedocs.org/user_builds/django-modern-rest/checkouts/0.7.0/dmr/endpoint.py</code>, line 197, in __call__
          

          
            <div class="context" id="c140501913192576">
              
                <ol start="190" class="pre-context" id="pre140501913192576">
                
                  <li onclick="toggle('pre140501913192576', 'post140501913192576')"><pre>    def __call__(</pre></li>
                
                  <li onclick="toggle('pre140501913192576', 'post140501913192576')"><pre>        self,</pre></li>
                
                  <li onclick="toggle('pre140501913192576', 'post140501913192576')"><pre>        controller: &#x27;Controller[BaseSerializer]&#x27;,</pre></li>
                
                  <li onclick="toggle('pre140501913192576', 'post140501913192576')"><pre>        *args: Any,</pre></li>
                
                  <li onclick="toggle('pre140501913192576', 'post140501913192576')"><pre>        **kwargs: Any,</pre></li>
                
                  <li onclick="toggle('pre140501913192576', 'post140501913192576')"><pre>    ) -&gt; HttpResponseBase:</pre></li>
                
                  <li onclick="toggle('pre140501913192576', 'post140501913192576')"><pre>        &quot;&quot;&quot;Run the endpoint and return the response.&quot;&quot;&quot;</pre></li>
                
                </ol>
              
              <ol start="197" class="context-line">
                <li onclick="toggle('pre140501913192576', 'post140501913192576')"><pre>        return self._func(  # type: ignore[no-any-return]
                    </pre> <span>…</span></li>
              </ol>
              
                <ol start='198' class="post-context" id="post140501913192576">
                  
                  <li onclick="toggle('pre140501913192576', 'post140501913192576')"><pre>            controller,</pre></li>
                  
                  <li onclick="toggle('pre140501913192576', 'post140501913192576')"><pre>            *args,</pre></li>
                  
                  <li onclick="toggle('pre140501913192576', 'post140501913192576')"><pre>            **kwargs,</pre></li>
                  
                  <li onclick="toggle('pre140501913192576', 'post140501913192576')"><pre>        )</pre></li>
                  
                  <li onclick="toggle('pre140501913192576', 'post140501913192576')"><pre></pre></li>
                  
                  <li onclick="toggle('pre140501913192576', 'post140501913192576')"><pre>    def handle_error(</pre></li>
                  
              </ol>
              
            </div>
          

          
            
              <details>
                <summary class="commands">Local vars</summary>
            
            <table class="vars" id="v140501913192576">
              <thead>
                <tr>
                  <th scope="col">Variable</th>
                  <th scope="col">Value</th>
                </tr>
              </thead>
              <tbody>
                
                  <tr>
                    <td>args</td>
                    <td class="code"><pre>()</pre></td>
                  </tr>
                
                  <tr>
                    <td>controller</td>
                    <td class="code"><pre>&lt;examples.error_handling.pydantic_validation_error.PongController object at 0x7fc926e5a7b0&gt;</pre></td>
                  </tr>
                
                  <tr>
                    <td>kwargs</td>
                    <td class="code"><pre>{}</pre></td>
                  </tr>
                
                  <tr>
                    <td>self</td>
                    <td class="code"><pre>&lt;dmr.endpoint.Endpoint object at 0x7fc926dc93f0&gt;</pre></td>
                  </tr>
                
              </tbody>
            </table>
            </details>
          
        </li>
      
        
        <li class="frame user">
          
            <code class="fname">/home/docs/checkouts/readthedocs.org/user_builds/django-modern-rest/checkouts/0.7.0/dmr/endpoint.py</code>, line 401, in decorator
          

          
            <div class="context" id="c140501913189568">
              
                <ol start="394" class="pre-context" id="pre140501913189568">
                
                  <li onclick="toggle('pre140501913189568', 'post140501913189568')"><pre>                    exc.raw_data,</pre></li>
                
                  <li onclick="toggle('pre140501913189568', 'post140501913189568')"><pre>                    status_code=exc.status_code,</pre></li>
                
                  <li onclick="toggle('pre140501913189568', 'post140501913189568')"><pre>                    headers=exc.headers,</pre></li>
                
                  <li onclick="toggle('pre140501913189568', 'post140501913189568')"><pre>                    cookies=getattr(exc, &#x27;cookies&#x27;, None),</pre></li>
                
                  <li onclick="toggle('pre140501913189568', 'post140501913189568')"><pre>                    renderer=getattr(exc, &#x27;renderer&#x27;, None),</pre></li>
                
                  <li onclick="toggle('pre140501913189568', 'post140501913189568')"><pre>                )</pre></li>
                
                  <li onclick="toggle('pre140501913189568', 'post140501913189568')"><pre>            except Exception as exc:</pre></li>
                
                </ol>
              
              <ol start="401" class="context-line">
                <li onclick="toggle('pre140501913189568', 'post140501913189568')"><pre>                func_result = self.handle_error(controller, exc)
                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^</pre> <span>…</span></li>
              </ol>
              
                <ol start='402' class="post-context" id="post140501913189568">
                  
                  <li onclick="toggle('pre140501913189568', 'post140501913189568')"><pre>            return self._make_http_response(controller, func_result)</pre></li>
                  
                  <li onclick="toggle('pre140501913189568', 'post140501913189568')"><pre></pre></li>
                  
                  <li onclick="toggle('pre140501913189568', 'post140501913189568')"><pre>        return decorator</pre></li>
                  
                  <li onclick="toggle('pre140501913189568', 'post140501913189568')"><pre></pre></li>
                  
                  <li onclick="toggle('pre140501913189568', 'post140501913189568')"><pre>    # Sync checks:</pre></li>
                  
                  <li onclick="toggle('pre140501913189568', 'post140501913189568')"><pre></pre></li>
                  
              </ol>
              
            </div>
          

          
            
              <details>
                <summary class="commands">Local vars</summary>
            
            <table class="vars" id="v140501913189568">
              <thead>
                <tr>
                  <th scope="col">Variable</th>
                  <th scope="col">Value</th>
                </tr>
              </thead>
              <tbody>
                
                  <tr>
                    <td>args</td>
                    <td class="code"><pre>()</pre></td>
                  </tr>
                
                  <tr>
                    <td>context</td>
                    <td class="code"><pre>{}</pre></td>
                  </tr>
                
                  <tr>
                    <td>controller</td>
                    <td class="code"><pre>&lt;examples.error_handling.pydantic_validation_error.PongController object at 0x7fc926e5a7b0&gt;</pre></td>
                  </tr>
                
                  <tr>
                    <td>func</td>
                    <td class="code"><pre>&lt;function PongController.get at 0x7fc926ddb100&gt;</pre></td>
                  </tr>
                
                  <tr>
                    <td>kwargs</td>
                    <td class="code"><pre>{}</pre></td>
                  </tr>
                
                  <tr>
                    <td>self</td>
                    <td class="code"><pre>&lt;dmr.endpoint.Endpoint object at 0x7fc926dc93f0&gt;</pre></td>
                  </tr>
                
              </tbody>
            </table>
            </details>
          
        </li>
      
        
        <li class="frame user">
          
            <code class="fname">/home/docs/checkouts/readthedocs.org/user_builds/django-modern-rest/checkouts/0.7.0/dmr/endpoint.py</code>, line 236, in handle_error
          

          
            <div class="context" id="c140501913178752">
              
                <ol start="229" class="pre-context" id="pre140501913178752">
                
                  <li onclick="toggle('pre140501913178752', 'post140501913178752')"><pre>            return controller.handle_error(</pre></li>
                
                  <li onclick="toggle('pre140501913178752', 'post140501913178752')"><pre>                self,</pre></li>
                
                  <li onclick="toggle('pre140501913178752', 'post140501913178752')"><pre>                controller,</pre></li>
                
                  <li onclick="toggle('pre140501913178752', 'post140501913178752')"><pre>                exc,</pre></li>
                
                  <li onclick="toggle('pre140501913178752', 'post140501913178752')"><pre>            )</pre></li>
                
                  <li onclick="toggle('pre140501913178752', 'post140501913178752')"><pre>        except Exception:</pre></li>
                
                  <li onclick="toggle('pre140501913178752', 'post140501913178752')"><pre>            # And the last option is to handle error globally:</pre></li>
                
                </ol>
              
              <ol start="236" class="context-line">
                <li onclick="toggle('pre140501913178752', 'post140501913178752')"><pre>            return self._global_error_handler(controller, exc)
                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^</pre> <span>…</span></li>
              </ol>
              
                <ol start='237' class="post-context" id="post140501913178752">
                  
                  <li onclick="toggle('pre140501913178752', 'post140501913178752')"><pre></pre></li>
                  
                  <li onclick="toggle('pre140501913178752', 'post140501913178752')"><pre>    async def handle_async_error(</pre></li>
                  
                  <li onclick="toggle('pre140501913178752', 'post140501913178752')"><pre>        self,</pre></li>
                  
                  <li onclick="toggle('pre140501913178752', 'post140501913178752')"><pre>        controller: &#x27;Controller[BaseSerializer]&#x27;,</pre></li>
                  
                  <li onclick="toggle('pre140501913178752', 'post140501913178752')"><pre>        exc: Exception,</pre></li>
                  
                  <li onclick="toggle('pre140501913178752', 'post140501913178752')"><pre>    ) -&gt; HttpResponse:</pre></li>
                  
              </ol>
              
            </div>
          

          
            
              <details>
                <summary class="commands">Local vars</summary>
            
            <table class="vars" id="v140501913178752">
              <thead>
                <tr>
                  <th scope="col">Variable</th>
                  <th scope="col">Value</th>
                </tr>
              </thead>
              <tbody>
                
                  <tr>
                    <td>controller</td>
                    <td class="code"><pre>&lt;examples.error_handling.pydantic_validation_error.PongController object at 0x7fc926e5a7b0&gt;</pre></td>
                  </tr>
                
                  <tr>
                    <td>exc</td>
                    <td class="code"><pre>1 validation error for Pong
message
  Input should be &#x27;pong&#x27; [type=literal_error, input_value=&#x27;wrong&#x27;, input_type=str]
    For further information visit https://errors.pydantic.dev/2.13/v/literal_error</pre></td>
                  </tr>
                
                  <tr>
                    <td>self</td>
                    <td class="code"><pre>&lt;dmr.endpoint.Endpoint object at 0x7fc926dc93f0&gt;</pre></td>
                  </tr>
                
              </tbody>
            </table>
            </details>
          
        </li>
      
        
        <li class="frame user">
          
            <code class="fname">/home/docs/checkouts/readthedocs.org/user_builds/django-modern-rest/checkouts/0.7.0/dmr/endpoint.py</code>, line 577, in _global_error_handler
          

          
            <div class="context" id="c140501920193024">
              
                <ol start="570" class="pre-context" id="pre140501920193024">
                
                  <li onclick="toggle('pre140501920193024', 'post140501920193024')"><pre>        exc: Exception,</pre></li>
                
                  <li onclick="toggle('pre140501920193024', 'post140501920193024')"><pre>    ) -&gt; HttpResponse:</pre></li>
                
                  <li onclick="toggle('pre140501920193024', 'post140501920193024')"><pre>        &quot;&quot;&quot;</pre></li>
                
                  <li onclick="toggle('pre140501920193024', 'post140501920193024')"><pre>        Import the global error handling and call it.</pre></li>
                
                  <li onclick="toggle('pre140501920193024', 'post140501920193024')"><pre></pre></li>
                
                  <li onclick="toggle('pre140501920193024', 'post140501920193024')"><pre>        If not class level error handling has happened.</pre></li>
                
                  <li onclick="toggle('pre140501920193024', 'post140501920193024')"><pre>        &quot;&quot;&quot;</pre></li>
                
                </ol>
              
              <ol start="577" class="context-line">
                <li onclick="toggle('pre140501920193024', 'post140501920193024')"><pre>        return resolve_setting(  # type: ignore[no-any-return]
                    ^^^^^^^^^^^^^^^^^</pre> <span>…</span></li>
              </ol>
              
                <ol start='578' class="post-context" id="post140501920193024">
                  
                  <li onclick="toggle('pre140501920193024', 'post140501920193024')"><pre>            Settings.global_error_handler,</pre></li>
                  
                  <li onclick="toggle('pre140501920193024', 'post140501920193024')"><pre>            import_string=True,</pre></li>
                  
                  <li onclick="toggle('pre140501920193024', 'post140501920193024')"><pre>        )(self, controller, exc)</pre></li>
                  
                  <li onclick="toggle('pre140501920193024', 'post140501920193024')"><pre></pre></li>
                  
                  <li onclick="toggle('pre140501920193024', 'post140501920193024')"><pre></pre></li>
                  
                  <li onclick="toggle('pre140501920193024', 'post140501920193024')"><pre>_ParamT = ParamSpec(&#x27;_ParamT&#x27;)</pre></li>
                  
              </ol>
              
            </div>
          

          
            
              <details>
                <summary class="commands">Local vars</summary>
            
            <table class="vars" id="v140501920193024">
              <thead>
                <tr>
                  <th scope="col">Variable</th>
                  <th scope="col">Value</th>
                </tr>
              </thead>
              <tbody>
                
                  <tr>
                    <td>controller</td>
                    <td class="code"><pre>&lt;examples.error_handling.pydantic_validation_error.PongController object at 0x7fc926e5a7b0&gt;</pre></td>
                  </tr>
                
                  <tr>
                    <td>exc</td>
                    <td class="code"><pre>1 validation error for Pong
message
  Input should be &#x27;pong&#x27; [type=literal_error, input_value=&#x27;wrong&#x27;, input_type=str]
    For further information visit https://errors.pydantic.dev/2.13/v/literal_error</pre></td>
                  </tr>
                
                  <tr>
                    <td>self</td>
                    <td class="code"><pre>&lt;dmr.endpoint.Endpoint object at 0x7fc926dc93f0&gt;</pre></td>
                  </tr>
                
              </tbody>
            </table>
            </details>
          
        </li>
      
        
        <li class="frame user">
          
            <code class="fname">/home/docs/checkouts/readthedocs.org/user_builds/django-modern-rest/checkouts/0.7.0/dmr/endpoint.py</code>, line 229, in handle_error
          

          
            <div class="context" id="c140501913179648">
              
                <ol start="222" class="pre-context" id="pre140501913179648">
                
                  <li onclick="toggle('pre140501913179648', 'post140501913179648')"><pre>                )</pre></li>
                
                  <li onclick="toggle('pre140501913179648', 'post140501913179648')"><pre>            except Exception:  # noqa: S110</pre></li>
                
                  <li onclick="toggle('pre140501913179648', 'post140501913179648')"><pre>                # We don&#x27;t use `suppress` here for speed.</pre></li>
                
                  <li onclick="toggle('pre140501913179648', 'post140501913179648')"><pre>                pass  # noqa: WPS420</pre></li>
                
                  <li onclick="toggle('pre140501913179648', 'post140501913179648')"><pre>        # Per-endpoint error handler didn&#x27;t work.</pre></li>
                
                  <li onclick="toggle('pre140501913179648', 'post140501913179648')"><pre>        # Now, try the per-controller one.</pre></li>
                
                  <li onclick="toggle('pre140501913179648', 'post140501913179648')"><pre>        try:</pre></li>
                
                </ol>
              
              <ol start="229" class="context-line">
                <li onclick="toggle('pre140501913179648', 'post140501913179648')"><pre>            return controller.handle_error(
                        </pre> <span>…</span></li>
              </ol>
              
                <ol start='230' class="post-context" id="post140501913179648">
                  
                  <li onclick="toggle('pre140501913179648', 'post140501913179648')"><pre>                self,</pre></li>
                  
                  <li onclick="toggle('pre140501913179648', 'post140501913179648')"><pre>                controller,</pre></li>
                  
                  <li onclick="toggle('pre140501913179648', 'post140501913179648')"><pre>                exc,</pre></li>
                  
                  <li onclick="toggle('pre140501913179648', 'post140501913179648')"><pre>            )</pre></li>
                  
                  <li onclick="toggle('pre140501913179648', 'post140501913179648')"><pre>        except Exception:</pre></li>
                  
                  <li onclick="toggle('pre140501913179648', 'post140501913179648')"><pre>            # And the last option is to handle error globally:</pre></li>
                  
              </ol>
              
            </div>
          

          
            
              <details>
                <summary class="commands">Local vars</summary>
            
            <table class="vars" id="v140501913179648">
              <thead>
                <tr>
                  <th scope="col">Variable</th>
                  <th scope="col">Value</th>
                </tr>
              </thead>
              <tbody>
                
                  <tr>
                    <td>controller</td>
                    <td class="code"><pre>&lt;examples.error_handling.pydantic_validation_error.PongController object at 0x7fc926e5a7b0&gt;</pre></td>
                  </tr>
                
                  <tr>
                    <td>exc</td>
                    <td class="code"><pre>1 validation error for Pong
message
  Input should be &#x27;pong&#x27; [type=literal_error, input_value=&#x27;wrong&#x27;, input_type=str]
    For further information visit https://errors.pydantic.dev/2.13/v/literal_error</pre></td>
                  </tr>
                
                  <tr>
                    <td>self</td>
                    <td class="code"><pre>&lt;dmr.endpoint.Endpoint object at 0x7fc926dc93f0&gt;</pre></td>
                  </tr>
                
              </tbody>
            </table>
            </details>
          
        </li>
      
        
        <li class="frame user">
          
            <code class="fname">/home/docs/checkouts/readthedocs.org/user_builds/django-modern-rest/checkouts/0.7.0/dmr/endpoint.py</code>, line 391, in decorator
          

          
            <div class="context" id="c140501913179712">
              
                <ol start="384" class="pre-context" id="pre140501913179712">
                
                  <li onclick="toggle('pre140501913179712', 'post140501913179712')"><pre>                # Run checks:</pre></li>
                
                  <li onclick="toggle('pre140501913179712', 'post140501913179712')"><pre>                self._run_checks(controller)</pre></li>
                
                  <li onclick="toggle('pre140501913179712', 'post140501913179712')"><pre></pre></li>
                
                  <li onclick="toggle('pre140501913179712', 'post140501913179712')"><pre>                # Parse request:</pre></li>
                
                  <li onclick="toggle('pre140501913179712', 'post140501913179712')"><pre>                context = self._serializer_context(self, controller)</pre></li>
                
                  <li onclick="toggle('pre140501913179712', 'post140501913179712')"><pre></pre></li>
                
                  <li onclick="toggle('pre140501913179712', 'post140501913179712')"><pre>                # Return response:</pre></li>
                
                </ol>
              
              <ol start="391" class="context-line">
                <li onclick="toggle('pre140501913179712', 'post140501913179712')"><pre>                func_result = func(controller, **context)
                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^</pre> <span>…</span></li>
              </ol>
              
                <ol start='392' class="post-context" id="post140501913179712">
                  
                  <li onclick="toggle('pre140501913179712', 'post140501913179712')"><pre>            except (APIError, APIRedirectError) as exc:</pre></li>
                  
                  <li onclick="toggle('pre140501913179712', 'post140501913179712')"><pre>                func_result = controller.to_error(</pre></li>
                  
                  <li onclick="toggle('pre140501913179712', 'post140501913179712')"><pre>                    exc.raw_data,</pre></li>
                  
                  <li onclick="toggle('pre140501913179712', 'post140501913179712')"><pre>                    status_code=exc.status_code,</pre></li>
                  
                  <li onclick="toggle('pre140501913179712', 'post140501913179712')"><pre>                    headers=exc.headers,</pre></li>
                  
                  <li onclick="toggle('pre140501913179712', 'post140501913179712')"><pre>                    cookies=getattr(exc, &#x27;cookies&#x27;, None),</pre></li>
                  
              </ol>
              
            </div>
          

          
            
              <details>
                <summary class="commands">Local vars</summary>
            
            <table class="vars" id="v140501913179712">
              <thead>
                <tr>
                  <th scope="col">Variable</th>
                  <th scope="col">Value</th>
                </tr>
              </thead>
              <tbody>
                
                  <tr>
                    <td>args</td>
                    <td class="code"><pre>()</pre></td>
                  </tr>
                
                  <tr>
                    <td>context</td>
                    <td class="code"><pre>{}</pre></td>
                  </tr>
                
                  <tr>
                    <td>controller</td>
                    <td class="code"><pre>&lt;examples.error_handling.pydantic_validation_error.PongController object at 0x7fc926e5a7b0&gt;</pre></td>
                  </tr>
                
                  <tr>
                    <td>func</td>
                    <td class="code"><pre>&lt;function PongController.get at 0x7fc926ddb100&gt;</pre></td>
                  </tr>
                
                  <tr>
                    <td>kwargs</td>
                    <td class="code"><pre>{}</pre></td>
                  </tr>
                
                  <tr>
                    <td>self</td>
                    <td class="code"><pre>&lt;dmr.endpoint.Endpoint object at 0x7fc926dc93f0&gt;</pre></td>
                  </tr>
                
              </tbody>
            </table>
            </details>
          
        </li>
      
        
        <li class="frame user">
          
            <code class="fname">/home/docs/checkouts/readthedocs.org/user_builds/django-modern-rest/checkouts/0.7.0/docs/examples/error_handling/pydantic_validation_error.py</code>, line 17, in get
          

          
            <div class="context" id="c140501913179584">
              
                <ol start="10" class="pre-context" id="pre140501913179584">
                
                  <li onclick="toggle('pre140501913179584', 'post140501913179584')"><pre>    message: Literal[&#x27;pong&#x27;]</pre></li>
                
                  <li onclick="toggle('pre140501913179584', 'post140501913179584')"><pre></pre></li>
                
                  <li onclick="toggle('pre140501913179584', 'post140501913179584')"><pre></pre></li>
                
                  <li onclick="toggle('pre140501913179584', 'post140501913179584')"><pre>class PongController(Controller[PydanticSerializer]):</pre></li>
                
                  <li onclick="toggle('pre140501913179584', 'post140501913179584')"><pre>    def get(self) -&gt; Pong:</pre></li>
                
                  <li onclick="toggle('pre140501913179584', 'post140501913179584')"><pre>        # This will trigger `pydantic.ValidationError`,</pre></li>
                
                  <li onclick="toggle('pre140501913179584', 'post140501913179584')"><pre>        # because `message` must be `&#x27;pong&#x27;`, not `&#x27;wrong&#x27;`:</pre></li>
                
                </ol>
              
              <ol start="17" class="context-line">
                <li onclick="toggle('pre140501913179584', 'post140501913179584')"><pre>        return Pong(message=&#x27;wrong&#x27;)
                   ^^^^^^^^^^^^^^^^^^^^^</pre> <span>…</span></li>
              </ol>
              
                <ol start='18' class="post-context" id="post140501913179584">
                  
                  <li onclick="toggle('pre140501913179584', 'post140501913179584')"><pre></pre></li>
                  
                  <li onclick="toggle('pre140501913179584', 'post140501913179584')"><pre></pre></li>
                  
                  <li onclick="toggle('pre140501913179584', 'post140501913179584')"><pre># run: {&quot;controller&quot;: &quot;PongController&quot;, &quot;method&quot;: &quot;get&quot;, &quot;url&quot;: &quot;/api/ping/&quot;, &quot;curl_args&quot;: [&quot;-D&quot;, &quot;-&quot;], &quot;assert-error-text&quot;: &quot;Internal server error&quot;, &quot;fail-with-body&quot;: false}  # noqa: ERA001, E501</pre></li>
                  
              </ol>
              
            </div>
          

          
            
              <details>
                <summary class="commands">Local vars</summary>
            
            <table class="vars" id="v140501913179584">
              <thead>
                <tr>
                  <th scope="col">Variable</th>
                  <th scope="col">Value</th>
                </tr>
              </thead>
              <tbody>
                
                  <tr>
                    <td>self</td>
                    <td class="code"><pre>&lt;examples.error_handling.pydantic_validation_error.PongController object at 0x7fc926e5a7b0&gt;</pre></td>
                  </tr>
                
              </tbody>
            </table>
            </details>
          
        </li>
      
        
        <li class="frame user">
          
            <code class="fname">/home/docs/checkouts/readthedocs.org/user_builds/django-modern-rest/envs/0.7.0/lib/python3.12/site-packages/pydantic/main.py</code>, line 263, in __init__
          

          
            <div class="context" id="c140501913179264">
              
                <ol start="256" class="pre-context" id="pre140501913179264">
                
                  <li onclick="toggle('pre140501913179264', 'post140501913179264')"><pre>        Raises [`ValidationError`][pydantic_core.ValidationError] if the input data cannot be</pre></li>
                
                  <li onclick="toggle('pre140501913179264', 'post140501913179264')"><pre>        validated to form a valid model.</pre></li>
                
                  <li onclick="toggle('pre140501913179264', 'post140501913179264')"><pre></pre></li>
                
                  <li onclick="toggle('pre140501913179264', 'post140501913179264')"><pre>        `self` is explicitly positional-only to allow `self` as a field name.</pre></li>
                
                  <li onclick="toggle('pre140501913179264', 'post140501913179264')"><pre>        &quot;&quot;&quot;</pre></li>
                
                  <li onclick="toggle('pre140501913179264', 'post140501913179264')"><pre>        # `__tracebackhide__` tells pytest and some other tools to omit this function from tracebacks</pre></li>
                
                  <li onclick="toggle('pre140501913179264', 'post140501913179264')"><pre>        __tracebackhide__ = True</pre></li>
                
                </ol>
              
              <ol start="263" class="context-line">
                <li onclick="toggle('pre140501913179264', 'post140501913179264')"><pre>        validated_self = self.__pydantic_validator__.validate_python(data, self_instance=self)
                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^</pre> <span>…</span></li>
              </ol>
              
                <ol start='264' class="post-context" id="post140501913179264">
                  
                  <li onclick="toggle('pre140501913179264', 'post140501913179264')"><pre>        if self is not validated_self:</pre></li>
                  
                  <li onclick="toggle('pre140501913179264', 'post140501913179264')"><pre>            warnings.warn(</pre></li>
                  
                  <li onclick="toggle('pre140501913179264', 'post140501913179264')"><pre>                &#x27;A custom validator is returning a value other than `self`.\n&#x27;</pre></li>
                  
                  <li onclick="toggle('pre140501913179264', 'post140501913179264')"><pre>                &quot;Returning anything other than `self` from a top level model validator isn&#x27;t supported when validating via `__init__`.\n&quot;</pre></li>
                  
                  <li onclick="toggle('pre140501913179264', 'post140501913179264')"><pre>                &#x27;See the `model_validator` docs (https://docs.pydantic.dev/latest/concepts/validators/#model-validators) for more details.&#x27;,</pre></li>
                  
                  <li onclick="toggle('pre140501913179264', 'post140501913179264')"><pre>                stacklevel=2,</pre></li>
                  
              </ol>
              
            </div>
          

          
            
              <details>
                <summary class="commands">Local vars</summary>
            
            <table class="vars" id="v140501913179264">
              <thead>
                <tr>
                  <th scope="col">Variable</th>
                  <th scope="col">Value</th>
                </tr>
              </thead>
              <tbody>
                
                  <tr>
                    <td>__tracebackhide__</td>
                    <td class="code"><pre>True</pre></td>
                  </tr>
                
                  <tr>
                    <td>data</td>
                    <td class="code"><pre>{&#x27;message&#x27;: &#x27;wrong&#x27;}</pre></td>
                  </tr>
                
                  <tr>
                    <td>self</td>
                    <td class="code"><pre>Pong()</pre></td>
                  </tr>
                
              </tbody>
            </table>
            </details>
          
        </li>
      
    </ul>
  </div>

  <form action="https://dpaste.com/" name="pasteform" id="pasteform" method="post">
  <div id="pastebinTraceback" class="pastebin">
    <input type="hidden" name="language" value="PythonConsole">
    <input type="hidden" name="title"
      value="ValidationError at /api/ping/">
    <input type="hidden" name="source" value="Django Dpaste Agent">
    <input type="hidden" name="poster" value="Django">
    <textarea name="content" id="traceback_area" cols="140" rows="25">
Environment:


Request Method: GET
Request URL: http://127.0.0.1:58663/api/ping/

Django Version: 5.2.13
Python Version: 3.12.10
Installed Applications:
[&#x27;django.contrib.auth&#x27;,
 &#x27;django.contrib.sessions&#x27;,
 &#x27;django.contrib.contenttypes&#x27;,
 &#x27;dmr&#x27;,
 &#x27;dmr.security.jwt.blocklist&#x27;,
 &#x27;server.apps.model_simple&#x27;,
 &#x27;server.apps.model_fk&#x27;]
Installed Middleware:
[&#x27;django.middleware.security.SecurityMiddleware&#x27;,
 &#x27;django.contrib.sessions.middleware.SessionMiddleware&#x27;,
 &#x27;django.middleware.common.CommonMiddleware&#x27;,
 &#x27;django.middleware.csrf.CsrfViewMiddleware&#x27;,
 &#x27;django.contrib.auth.middleware.AuthenticationMiddleware&#x27;,
 &#x27;django.middleware.locale.LocaleMiddleware&#x27;,
 &#x27;django.contrib.messages.middleware.MessageMiddleware&#x27;,
 &#x27;django.middleware.clickjacking.XFrameOptionsMiddleware&#x27;]



Traceback (most recent call last):
  File "/home/docs/checkouts/readthedocs.org/user_builds/django-modern-rest/envs/0.7.0/lib/python3.12/site-packages/django/core/handlers/exception.py", line 42, in inner
    response = await get_response(request)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/docs/checkouts/readthedocs.org/user_builds/django-modern-rest/envs/0.7.0/lib/python3.12/site-packages/django/core/handlers/base.py", line 253, in _get_response_async
    response = await wrapped_callback(
               
  File "/home/docs/.asdf/installs/python/3.12.10/lib/python3.12/concurrent/futures/thread.py", line 59, in run
    result = self.fn(*self.args, **self.kwargs)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/docs/checkouts/readthedocs.org/user_builds/django-modern-rest/envs/0.7.0/lib/python3.12/site-packages/django/views/decorators/csrf.py", line 65, in _view_wrapper
    return view_func(request, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/docs/checkouts/readthedocs.org/user_builds/django-modern-rest/envs/0.7.0/lib/python3.12/site-packages/django/views/generic/base.py", line 105, in view
    return self.dispatch(request, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/docs/checkouts/readthedocs.org/user_builds/django-modern-rest/checkouts/0.7.0/dmr/controller.py", line 241, in dispatch
    return endpoint(self, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/docs/checkouts/readthedocs.org/user_builds/django-modern-rest/checkouts/0.7.0/dmr/endpoint.py", line 197, in __call__
    return self._func(  # type: ignore[no-any-return]
           
  File "/home/docs/checkouts/readthedocs.org/user_builds/django-modern-rest/checkouts/0.7.0/dmr/endpoint.py", line 401, in decorator
    func_result = self.handle_error(controller, exc)
                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/docs/checkouts/readthedocs.org/user_builds/django-modern-rest/checkouts/0.7.0/dmr/endpoint.py", line 236, in handle_error
    return self._global_error_handler(controller, exc)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/docs/checkouts/readthedocs.org/user_builds/django-modern-rest/checkouts/0.7.0/dmr/endpoint.py", line 577, in _global_error_handler
    return resolve_setting(  # type: ignore[no-any-return]
           ^^^^^^^^^^^^^^^^^
  File "/home/docs/checkouts/readthedocs.org/user_builds/django-modern-rest/checkouts/0.7.0/dmr/endpoint.py", line 229, in handle_error
    return controller.handle_error(
           
  File "/home/docs/checkouts/readthedocs.org/user_builds/django-modern-rest/checkouts/0.7.0/dmr/endpoint.py", line 391, in decorator
    func_result = func(controller, **context)
                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/docs/checkouts/readthedocs.org/user_builds/django-modern-rest/checkouts/0.7.0/docs/examples/error_handling/pydantic_validation_error.py", line 17, in get
    return Pong(message=&#x27;wrong&#x27;)
           ^^^^^^^^^^^^^^^^^^^^^
  File "/home/docs/checkouts/readthedocs.org/user_builds/django-modern-rest/envs/0.7.0/lib/python3.12/site-packages/pydantic/main.py", line 263, in __init__
    validated_self = self.__pydantic_validator__.validate_python(data, self_instance=self)
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Exception Type: ValidationError at /api/ping/
Exception Value: 1 validation error for Pong
message
  Input should be &#x27;pong&#x27; [type=literal_error, input_value=&#x27;wrong&#x27;, input_type=str]
    For further information visit https://errors.pydantic.dev/2.13/v/literal_error
</textarea>
  <br><br>
  <input type="submit" value="Share this traceback on a public website">
  </div>
</form>

</div>


<div id="requestinfo">
  <h2>Request information</h2>


  
    <h3 id="user-info">USER</h3>
    <p>AnonymousUser</p>
  

  <h3 id="get-info">GET</h3>
  
    <p>No GET data</p>
  

  <h3 id="post-info">POST</h3>
  
    <p>No POST data</p>
  

  <h3 id="files-info">FILES</h3>
  
    <p>No FILES data</p>
  

  <h3 id="cookie-info">COOKIES</h3>
  
    <p>No cookie data</p>
  

  <h3 id="meta-info">META</h3>
  <table class="req">
    <thead>
      <tr>
        <th scope="col">Variable</th>
        <th scope="col">Value</th>
      </tr>
    </thead>
    <tbody>
      
        <tr>
          <td>HTTP_ACCEPT</td>
          <td class="code"><pre>&#x27;*/*&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>HTTP_HOST</td>
          <td class="code"><pre>&#x27;127.0.0.1:58663&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>HTTP_USER_AGENT</td>
          <td class="code"><pre>&#x27;curl/7.81.0&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>PATH_INFO</td>
          <td class="code"><pre>&#x27;/api/ping/&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>QUERY_STRING</td>
          <td class="code"><pre>&#x27;&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>REMOTE_ADDR</td>
          <td class="code"><pre>&#x27;127.0.0.1&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>REMOTE_HOST</td>
          <td class="code"><pre>&#x27;127.0.0.1&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>REMOTE_PORT</td>
          <td class="code"><pre>33068</pre></td>
        </tr>
      
        <tr>
          <td>REQUEST_METHOD</td>
          <td class="code"><pre>&#x27;GET&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>SCRIPT_NAME</td>
          <td class="code"><pre>&#x27;&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>SERVER_NAME</td>
          <td class="code"><pre>&#x27;127.0.0.1&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>SERVER_PORT</td>
          <td class="code"><pre>&#x27;58663&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>wsgi.multiprocess</td>
          <td class="code"><pre>True</pre></td>
        </tr>
      
        <tr>
          <td>wsgi.multithread</td>
          <td class="code"><pre>True</pre></td>
        </tr>
      
    </tbody>
  </table>


  <h3 id="settings-info">Settings</h3>
  <h4>Using settings module <code></code></h4>
  <table class="req">
    <thead>
      <tr>
        <th scope="col">Setting</th>
        <th scope="col">Value</th>
      </tr>
    </thead>
    <tbody>
      
        <tr>
          <td>ABSOLUTE_URL_OVERRIDES</td>
          <td class="code"><pre>{}</pre></td>
        </tr>
      
        <tr>
          <td>ADMINS</td>
          <td class="code"><pre>[]</pre></td>
        </tr>
      
        <tr>
          <td>ALLOWED_HOSTS</td>
          <td class="code"><pre>[&#x27;*&#x27;]</pre></td>
        </tr>
      
        <tr>
          <td>APPEND_SLASH</td>
          <td class="code"><pre>True</pre></td>
        </tr>
      
        <tr>
          <td>AUTHENTICATION_BACKENDS</td>
          <td class="code"><pre>&#x27;********************&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>AUTH_PASSWORD_VALIDATORS</td>
          <td class="code"><pre>&#x27;********************&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>AUTH_USER_MODEL</td>
          <td class="code"><pre>&#x27;********************&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>CACHES</td>
          <td class="code"><pre>{&#x27;default&#x27;: {&#x27;BACKEND&#x27;: &#x27;django.core.cache.backends.filebased.FileBasedCache&#x27;,
             &#x27;LOCATION&#x27;: &#x27;/home/docs/checkouts/readthedocs.org/user_builds/django-modern-rest/checkouts/0.7.0/docs/_build/default.cache&#x27;},
 &#x27;throttling&#x27;: {&#x27;BACKEND&#x27;: &#x27;django.core.cache.backends.filebased.FileBasedCache&#x27;,
                &#x27;LOCATION&#x27;: &#x27;/home/docs/checkouts/readthedocs.org/user_builds/django-modern-rest/checkouts/0.7.0/docs/_build/throttling.cache&#x27;}}</pre></td>
        </tr>
      
        <tr>
          <td>CACHE_MIDDLEWARE_ALIAS</td>
          <td class="code"><pre>&#x27;default&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>CACHE_MIDDLEWARE_KEY_PREFIX</td>
          <td class="code"><pre>&#x27;********************&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>CACHE_MIDDLEWARE_SECONDS</td>
          <td class="code"><pre>600</pre></td>
        </tr>
      
        <tr>
          <td>CSRF_COOKIE_AGE</td>
          <td class="code"><pre>31449600</pre></td>
        </tr>
      
        <tr>
          <td>CSRF_COOKIE_DOMAIN</td>
          <td class="code"><pre>None</pre></td>
        </tr>
      
        <tr>
          <td>CSRF_COOKIE_HTTPONLY</td>
          <td class="code"><pre>False</pre></td>
        </tr>
      
        <tr>
          <td>CSRF_COOKIE_NAME</td>
          <td class="code"><pre>&#x27;csrftoken&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>CSRF_COOKIE_PATH</td>
          <td class="code"><pre>&#x27;/&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>CSRF_COOKIE_SAMESITE</td>
          <td class="code"><pre>&#x27;Lax&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>CSRF_COOKIE_SECURE</td>
          <td class="code"><pre>False</pre></td>
        </tr>
      
        <tr>
          <td>CSRF_FAILURE_VIEW</td>
          <td class="code"><pre>&#x27;django.views.csrf.csrf_failure&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>CSRF_HEADER_NAME</td>
          <td class="code"><pre>&#x27;HTTP_X_CSRFTOKEN&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>CSRF_TRUSTED_ORIGINS</td>
          <td class="code"><pre>[]</pre></td>
        </tr>
      
        <tr>
          <td>CSRF_USE_SESSIONS</td>
          <td class="code"><pre>False</pre></td>
        </tr>
      
        <tr>
          <td>DATABASES</td>
          <td class="code"><pre>{&#x27;default&#x27;: {&#x27;ATOMIC_REQUESTS&#x27;: False,
             &#x27;AUTOCOMMIT&#x27;: True,
             &#x27;CONN_HEALTH_CHECKS&#x27;: False,
             &#x27;CONN_MAX_AGE&#x27;: 0,
             &#x27;ENGINE&#x27;: &#x27;django.db.backends.sqlite3&#x27;,
             &#x27;HOST&#x27;: &#x27;&#x27;,
             &#x27;NAME&#x27;: &#x27;_build/test.db&#x27;,
             &#x27;OPTIONS&#x27;: {},
             &#x27;PASSWORD&#x27;: &#x27;********************&#x27;,
             &#x27;PORT&#x27;: &#x27;&#x27;,
             &#x27;TEST&#x27;: {&#x27;CHARSET&#x27;: None,
                      &#x27;COLLATION&#x27;: None,
                      &#x27;MIGRATE&#x27;: True,
                      &#x27;MIRROR&#x27;: None,
                      &#x27;NAME&#x27;: None},
             &#x27;TIME_ZONE&#x27;: None,
             &#x27;USER&#x27;: &#x27;&#x27;}}</pre></td>
        </tr>
      
        <tr>
          <td>DATABASE_ROUTERS</td>
          <td class="code"><pre>[]</pre></td>
        </tr>
      
        <tr>
          <td>DATA_UPLOAD_MAX_MEMORY_SIZE</td>
          <td class="code"><pre>2621440</pre></td>
        </tr>
      
        <tr>
          <td>DATA_UPLOAD_MAX_NUMBER_FIELDS</td>
          <td class="code"><pre>1000</pre></td>
        </tr>
      
        <tr>
          <td>DATA_UPLOAD_MAX_NUMBER_FILES</td>
          <td class="code"><pre>100</pre></td>
        </tr>
      
        <tr>
          <td>DATETIME_FORMAT</td>
          <td class="code"><pre>&#x27;N j, Y, P&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>DATETIME_INPUT_FORMATS</td>
          <td class="code"><pre>[&#x27;%Y-%m-%d %H:%M:%S&#x27;,
 &#x27;%Y-%m-%d %H:%M:%S.%f&#x27;,
 &#x27;%Y-%m-%d %H:%M&#x27;,
 &#x27;%m/%d/%Y %H:%M:%S&#x27;,
 &#x27;%m/%d/%Y %H:%M:%S.%f&#x27;,
 &#x27;%m/%d/%Y %H:%M&#x27;,
 &#x27;%m/%d/%y %H:%M:%S&#x27;,
 &#x27;%m/%d/%y %H:%M:%S.%f&#x27;,
 &#x27;%m/%d/%y %H:%M&#x27;]</pre></td>
        </tr>
      
        <tr>
          <td>DATE_FORMAT</td>
          <td class="code"><pre>&#x27;N j, Y&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>DATE_INPUT_FORMATS</td>
          <td class="code"><pre>[&#x27;%Y-%m-%d&#x27;,
 &#x27;%m/%d/%Y&#x27;,
 &#x27;%m/%d/%y&#x27;,
 &#x27;%b %d %Y&#x27;,
 &#x27;%b %d, %Y&#x27;,
 &#x27;%d %b %Y&#x27;,
 &#x27;%d %b, %Y&#x27;,
 &#x27;%B %d %Y&#x27;,
 &#x27;%B %d, %Y&#x27;,
 &#x27;%d %B %Y&#x27;,
 &#x27;%d %B, %Y&#x27;]</pre></td>
        </tr>
      
        <tr>
          <td>DEBUG</td>
          <td class="code"><pre>True</pre></td>
        </tr>
      
        <tr>
          <td>DEBUG_PROPAGATE_EXCEPTIONS</td>
          <td class="code"><pre>False</pre></td>
        </tr>
      
        <tr>
          <td>DECIMAL_SEPARATOR</td>
          <td class="code"><pre>&#x27;.&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>DEFAULT_AUTO_FIELD</td>
          <td class="code"><pre>&#x27;django.db.models.BigAutoField&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>DEFAULT_CHARSET</td>
          <td class="code"><pre>&#x27;utf-8&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>DEFAULT_EXCEPTION_REPORTER</td>
          <td class="code"><pre>&#x27;django.views.debug.ExceptionReporter&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>DEFAULT_EXCEPTION_REPORTER_FILTER</td>
          <td class="code"><pre>&#x27;django.views.debug.SafeExceptionReporterFilter&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>DEFAULT_FROM_EMAIL</td>
          <td class="code"><pre>&#x27;webmaster@localhost&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>DEFAULT_INDEX_TABLESPACE</td>
          <td class="code"><pre>&#x27;&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>DEFAULT_TABLESPACE</td>
          <td class="code"><pre>&#x27;&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>DISALLOWED_USER_AGENTS</td>
          <td class="code"><pre>[]</pre></td>
        </tr>
      
        <tr>
          <td>EMAIL_BACKEND</td>
          <td class="code"><pre>&#x27;django.core.mail.backends.smtp.EmailBackend&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>EMAIL_HOST</td>
          <td class="code"><pre>&#x27;localhost&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>EMAIL_HOST_PASSWORD</td>
          <td class="code"><pre>&#x27;********************&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>EMAIL_HOST_USER</td>
          <td class="code"><pre>&#x27;&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>EMAIL_PORT</td>
          <td class="code"><pre>25</pre></td>
        </tr>
      
        <tr>
          <td>EMAIL_SSL_CERTFILE</td>
          <td class="code"><pre>None</pre></td>
        </tr>
      
        <tr>
          <td>EMAIL_SSL_KEYFILE</td>
          <td class="code"><pre>&#x27;********************&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>EMAIL_SUBJECT_PREFIX</td>
          <td class="code"><pre>&#x27;[Django] &#x27;</pre></td>
        </tr>
      
        <tr>
          <td>EMAIL_TIMEOUT</td>
          <td class="code"><pre>None</pre></td>
        </tr>
      
        <tr>
          <td>EMAIL_USE_LOCALTIME</td>
          <td class="code"><pre>False</pre></td>
        </tr>
      
        <tr>
          <td>EMAIL_USE_SSL</td>
          <td class="code"><pre>False</pre></td>
        </tr>
      
        <tr>
          <td>EMAIL_USE_TLS</td>
          <td class="code"><pre>False</pre></td>
        </tr>
      
        <tr>
          <td>FILE_UPLOAD_DIRECTORY_PERMISSIONS</td>
          <td class="code"><pre>None</pre></td>
        </tr>
      
        <tr>
          <td>FILE_UPLOAD_HANDLERS</td>
          <td class="code"><pre>[&#x27;django.core.files.uploadhandler.MemoryFileUploadHandler&#x27;,
 &#x27;django.core.files.uploadhandler.TemporaryFileUploadHandler&#x27;]</pre></td>
        </tr>
      
        <tr>
          <td>FILE_UPLOAD_MAX_MEMORY_SIZE</td>
          <td class="code"><pre>2621440</pre></td>
        </tr>
      
        <tr>
          <td>FILE_UPLOAD_PERMISSIONS</td>
          <td class="code"><pre>420</pre></td>
        </tr>
      
        <tr>
          <td>FILE_UPLOAD_TEMP_DIR</td>
          <td class="code"><pre>None</pre></td>
        </tr>
      
        <tr>
          <td>FIRST_DAY_OF_WEEK</td>
          <td class="code"><pre>0</pre></td>
        </tr>
      
        <tr>
          <td>FIXTURE_DIRS</td>
          <td class="code"><pre>[]</pre></td>
        </tr>
      
        <tr>
          <td>FORCE_SCRIPT_NAME</td>
          <td class="code"><pre>None</pre></td>
        </tr>
      
        <tr>
          <td>FORMAT_MODULE_PATH</td>
          <td class="code"><pre>None</pre></td>
        </tr>
      
        <tr>
          <td>FORMS_URLFIELD_ASSUME_HTTPS</td>
          <td class="code"><pre>False</pre></td>
        </tr>
      
        <tr>
          <td>FORM_RENDERER</td>
          <td class="code"><pre>&#x27;django.forms.renderers.DjangoTemplates&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>HTTP_BASIC_PASSWORD</td>
          <td class="code"><pre>&#x27;********************&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>HTTP_BASIC_USERNAME</td>
          <td class="code"><pre>&#x27;admin&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>IGNORABLE_404_URLS</td>
          <td class="code"><pre>[]</pre></td>
        </tr>
      
        <tr>
          <td>INSTALLED_APPS</td>
          <td class="code"><pre>[&#x27;django.contrib.auth&#x27;,
 &#x27;django.contrib.sessions&#x27;,
 &#x27;django.contrib.contenttypes&#x27;,
 &#x27;dmr&#x27;,
 &#x27;dmr.security.jwt.blocklist&#x27;,
 &#x27;server.apps.model_simple&#x27;,
 &#x27;server.apps.model_fk&#x27;]</pre></td>
        </tr>
      
        <tr>
          <td>INTERNAL_IPS</td>
          <td class="code"><pre>[]</pre></td>
        </tr>
      
        <tr>
          <td>LANGUAGES</td>
          <td class="code"><pre>((&#x27;en&#x27;, &#x27;English&#x27;), (&#x27;ru&#x27;, &#x27;Russian&#x27;))</pre></td>
        </tr>
      
        <tr>
          <td>LANGUAGES_BIDI</td>
          <td class="code"><pre>[&#x27;he&#x27;, &#x27;ar&#x27;, &#x27;ar-dz&#x27;, &#x27;ckb&#x27;, &#x27;fa&#x27;, &#x27;ug&#x27;, &#x27;ur&#x27;]</pre></td>
        </tr>
      
        <tr>
          <td>LANGUAGE_CODE</td>
          <td class="code"><pre>&#x27;en-us&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>LANGUAGE_COOKIE_AGE</td>
          <td class="code"><pre>None</pre></td>
        </tr>
      
        <tr>
          <td>LANGUAGE_COOKIE_DOMAIN</td>
          <td class="code"><pre>None</pre></td>
        </tr>
      
        <tr>
          <td>LANGUAGE_COOKIE_HTTPONLY</td>
          <td class="code"><pre>False</pre></td>
        </tr>
      
        <tr>
          <td>LANGUAGE_COOKIE_NAME</td>
          <td class="code"><pre>&#x27;django_language&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>LANGUAGE_COOKIE_PATH</td>
          <td class="code"><pre>&#x27;/&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>LANGUAGE_COOKIE_SAMESITE</td>
          <td class="code"><pre>None</pre></td>
        </tr>
      
        <tr>
          <td>LANGUAGE_COOKIE_SECURE</td>
          <td class="code"><pre>False</pre></td>
        </tr>
      
        <tr>
          <td>LOCALE_PATHS</td>
          <td class="code"><pre>[&#x27;/home/docs/checkouts/readthedocs.org/user_builds/django-modern-rest/checkouts/0.7.0/dmr/locale&#x27;]</pre></td>
        </tr>
      
        <tr>
          <td>LOGGING</td>
          <td class="code"><pre>{}</pre></td>
        </tr>
      
        <tr>
          <td>LOGGING_CONFIG</td>
          <td class="code"><pre>None</pre></td>
        </tr>
      
        <tr>
          <td>LOGIN_REDIRECT_URL</td>
          <td class="code"><pre>&#x27;/accounts/profile/&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>LOGIN_URL</td>
          <td class="code"><pre>&#x27;/accounts/login/&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>LOGOUT_REDIRECT_URL</td>
          <td class="code"><pre>None</pre></td>
        </tr>
      
        <tr>
          <td>MANAGERS</td>
          <td class="code"><pre>[]</pre></td>
        </tr>
      
        <tr>
          <td>MEDIA_ROOT</td>
          <td class="code"><pre>&#x27;&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>MEDIA_URL</td>
          <td class="code"><pre>&#x27;/&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>MESSAGE_STORAGE</td>
          <td class="code"><pre>&#x27;django.contrib.messages.storage.fallback.FallbackStorage&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>MIDDLEWARE</td>
          <td class="code"><pre>[&#x27;django.middleware.security.SecurityMiddleware&#x27;,
 &#x27;django.contrib.sessions.middleware.SessionMiddleware&#x27;,
 &#x27;django.middleware.common.CommonMiddleware&#x27;,
 &#x27;django.middleware.csrf.CsrfViewMiddleware&#x27;,
 &#x27;django.contrib.auth.middleware.AuthenticationMiddleware&#x27;,
 &#x27;django.middleware.locale.LocaleMiddleware&#x27;,
 &#x27;django.contrib.messages.middleware.MessageMiddleware&#x27;,
 &#x27;django.middleware.clickjacking.XFrameOptionsMiddleware&#x27;]</pre></td>
        </tr>
      
        <tr>
          <td>MIGRATION_MODULES</td>
          <td class="code"><pre>{}</pre></td>
        </tr>
      
        <tr>
          <td>MONTH_DAY_FORMAT</td>
          <td class="code"><pre>&#x27;F j&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>NUMBER_GROUPING</td>
          <td class="code"><pre>0</pre></td>
        </tr>
      
        <tr>
          <td>PASSWORD_HASHERS</td>
          <td class="code"><pre>&#x27;********************&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>PASSWORD_RESET_TIMEOUT</td>
          <td class="code"><pre>&#x27;********************&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>PREPEND_WWW</td>
          <td class="code"><pre>False</pre></td>
        </tr>
      
        <tr>
          <td>ROOT_URLCONF</td>
          <td class="code"><pre>&#x27;url_conf&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>SECRET_KEY</td>
          <td class="code"><pre>&#x27;********************&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>SECRET_KEY_FALLBACKS</td>
          <td class="code"><pre>&#x27;********************&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>SECURE_CONTENT_TYPE_NOSNIFF</td>
          <td class="code"><pre>True</pre></td>
        </tr>
      
        <tr>
          <td>SECURE_CROSS_ORIGIN_OPENER_POLICY</td>
          <td class="code"><pre>&#x27;same-origin&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>SECURE_HSTS_INCLUDE_SUBDOMAINS</td>
          <td class="code"><pre>False</pre></td>
        </tr>
      
        <tr>
          <td>SECURE_HSTS_PRELOAD</td>
          <td class="code"><pre>False</pre></td>
        </tr>
      
        <tr>
          <td>SECURE_HSTS_SECONDS</td>
          <td class="code"><pre>0</pre></td>
        </tr>
      
        <tr>
          <td>SECURE_PROXY_SSL_HEADER</td>
          <td class="code"><pre>None</pre></td>
        </tr>
      
        <tr>
          <td>SECURE_REDIRECT_EXEMPT</td>
          <td class="code"><pre>[]</pre></td>
        </tr>
      
        <tr>
          <td>SECURE_REFERRER_POLICY</td>
          <td class="code"><pre>&#x27;same-origin&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>SECURE_SSL_HOST</td>
          <td class="code"><pre>None</pre></td>
        </tr>
      
        <tr>
          <td>SECURE_SSL_REDIRECT</td>
          <td class="code"><pre>False</pre></td>
        </tr>
      
        <tr>
          <td>SERVER_EMAIL</td>
          <td class="code"><pre>&#x27;root@localhost&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>SESSION_CACHE_ALIAS</td>
          <td class="code"><pre>&#x27;default&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>SESSION_COOKIE_AGE</td>
          <td class="code"><pre>1209600</pre></td>
        </tr>
      
        <tr>
          <td>SESSION_COOKIE_DOMAIN</td>
          <td class="code"><pre>None</pre></td>
        </tr>
      
        <tr>
          <td>SESSION_COOKIE_HTTPONLY</td>
          <td class="code"><pre>True</pre></td>
        </tr>
      
        <tr>
          <td>SESSION_COOKIE_NAME</td>
          <td class="code"><pre>&#x27;sessionid&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>SESSION_COOKIE_PATH</td>
          <td class="code"><pre>&#x27;/&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>SESSION_COOKIE_SAMESITE</td>
          <td class="code"><pre>&#x27;Lax&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>SESSION_COOKIE_SECURE</td>
          <td class="code"><pre>False</pre></td>
        </tr>
      
        <tr>
          <td>SESSION_ENGINE</td>
          <td class="code"><pre>&#x27;django.contrib.sessions.backends.db&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>SESSION_EXPIRE_AT_BROWSER_CLOSE</td>
          <td class="code"><pre>False</pre></td>
        </tr>
      
        <tr>
          <td>SESSION_FILE_PATH</td>
          <td class="code"><pre>None</pre></td>
        </tr>
      
        <tr>
          <td>SESSION_SAVE_EVERY_REQUEST</td>
          <td class="code"><pre>False</pre></td>
        </tr>
      
        <tr>
          <td>SESSION_SERIALIZER</td>
          <td class="code"><pre>&#x27;django.contrib.sessions.serializers.JSONSerializer&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>SHORT_DATETIME_FORMAT</td>
          <td class="code"><pre>&#x27;m/d/Y P&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>SHORT_DATE_FORMAT</td>
          <td class="code"><pre>&#x27;m/d/Y&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>SIGNING_BACKEND</td>
          <td class="code"><pre>&#x27;django.core.signing.TimestampSigner&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>SILENCED_SYSTEM_CHECKS</td>
          <td class="code"><pre>[]</pre></td>
        </tr>
      
        <tr>
          <td>STATICFILES_DIRS</td>
          <td class="code"><pre>[]</pre></td>
        </tr>
      
        <tr>
          <td>STATICFILES_FINDERS</td>
          <td class="code"><pre>[&#x27;django.contrib.staticfiles.finders.FileSystemFinder&#x27;,
 &#x27;django.contrib.staticfiles.finders.AppDirectoriesFinder&#x27;]</pre></td>
        </tr>
      
        <tr>
          <td>STATIC_ROOT</td>
          <td class="code"><pre>None</pre></td>
        </tr>
      
        <tr>
          <td>STATIC_URL</td>
          <td class="code"><pre>None</pre></td>
        </tr>
      
        <tr>
          <td>STORAGES</td>
          <td class="code"><pre>{&#x27;default&#x27;: {&#x27;BACKEND&#x27;: &#x27;django.core.files.storage.FileSystemStorage&#x27;},
 &#x27;staticfiles&#x27;: {&#x27;BACKEND&#x27;: &#x27;django.contrib.staticfiles.storage.StaticFilesStorage&#x27;}}</pre></td>
        </tr>
      
        <tr>
          <td>TEMPLATES</td>
          <td class="code"><pre>[]</pre></td>
        </tr>
      
        <tr>
          <td>TEST_NON_SERIALIZED_APPS</td>
          <td class="code"><pre>[]</pre></td>
        </tr>
      
        <tr>
          <td>TEST_RUNNER</td>
          <td class="code"><pre>&#x27;django.test.runner.DiscoverRunner&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>THOUSAND_SEPARATOR</td>
          <td class="code"><pre>&#x27;,&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>TIME_FORMAT</td>
          <td class="code"><pre>&#x27;P&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>TIME_INPUT_FORMATS</td>
          <td class="code"><pre>[&#x27;%H:%M:%S&#x27;, &#x27;%H:%M:%S.%f&#x27;, &#x27;%H:%M&#x27;]</pre></td>
        </tr>
      
        <tr>
          <td>TIME_ZONE</td>
          <td class="code"><pre>&#x27;America/Chicago&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>USE_I18N</td>
          <td class="code"><pre>True</pre></td>
        </tr>
      
        <tr>
          <td>USE_THOUSAND_SEPARATOR</td>
          <td class="code"><pre>False</pre></td>
        </tr>
      
        <tr>
          <td>USE_TZ</td>
          <td class="code"><pre>True</pre></td>
        </tr>
      
        <tr>
          <td>USE_X_FORWARDED_HOST</td>
          <td class="code"><pre>False</pre></td>
        </tr>
      
        <tr>
          <td>USE_X_FORWARDED_PORT</td>
          <td class="code"><pre>False</pre></td>
        </tr>
      
        <tr>
          <td>WSGI_APPLICATION</td>
          <td class="code"><pre>None</pre></td>
        </tr>
      
        <tr>
          <td>X_FRAME_OPTIONS</td>
          <td class="code"><pre>&#x27;DENY&#x27;</pre></td>
        </tr>
      
        <tr>
          <td>YEAR_MONTH_FORMAT</td>
          <td class="code"><pre>&#x27;F Y&#x27;</pre></td>
        </tr>
      
    </tbody>
  </table>

</div>
</main>


  <footer id="explanation">
    <p>
      You’re seeing this error because you have <code>DEBUG = True</code> in your
      Django settings file. Change that to <code>False</code>, and Django will
      display a standard page generated by the handler for this status code.
    </p>
  </footer>

</body>
</html>

If you want to catch this error in a specific place and attach a specific behavior, use an error handler at a proper level.

For example, here we would handle it on a controller level:

Run result

$ curl http://127.0.0.1:8000/api/ping/ -D - -X GET
HTTP/1.1 500 Internal Server Error
date: Tue, 14 Apr 2026 17:08:31 GMT
server: uvicorn
Content-Type: application/json
X-Frame-Options: DENY
Vary: Accept-Language
Content-Language: en
Content-Length: 39
X-Content-Type-Options: nosniff
Referrer-Policy: same-origin
Cross-Origin-Opener-Policy: same-origin

{"detail":[{"msg":"Validation error"}]}

Now, the error is handled: we modified its error text and status code. Remember not to dump all the error information out to users, since they might contain sensitive data.

See also

See Handling 500 errors if you want to change the 500 error rendering.

API Reference

dmr.errors.global_error_handler(endpoint: Endpoint, controller: Controller[BaseSerializer], exc: Exception) HttpResponse[source]

Global error handler for all cases.

It is the last item in the chain that we try:

  1. Per endpoint configuration via handle_error() and handle_async_error() methods

  2. Per controller handlers

  3. This global handler, specified via the configuration

If some exception cannot be handled, it is just reraised.

Parameters:
  • endpoint – Endpoint where error happened.

  • controller – Controller instance that endpoint belongs to.

  • exc – Exception instance that happened.

Returns:

HttpResponse with proper response for this error. Or raise exc back.

Here’s an example that will produce {'detail': [{'msg': 'inf', 'type': 'user_msg'}]} for any ZeroDivisionError in your application:

>>> from http import HTTPStatus
>>> from django.http import HttpResponse
>>> from dmr.controller import Controller
>>> from dmr.endpoint import Endpoint
>>> from dmr.errors import global_error_handler, ErrorType

>>> def custom_error_handler(
...     controller: Controller,
...     endpoint: Endpoint,
...     exc: Exception,
... ) -> HttpResponse:
...     if isinstance(exc, ZeroDivisionError):
...         return controller.to_error(
...             controller.format_error(
...                 'inf',
...                 error_type=ErrorType.user_msg,
...             ),
...             status_code=HTTPStatus.NOT_IMPLEMENTED,
...         )
...     # Call the original handler to handle default errors:
...     return global_error_handler(controller, endpoint, exc)

>>> # And then in your settings file:
>>> DMR_SETTINGS = {
...     # Object `custom_error_handler` will also work:
...     'global_error_handler': 'path.to.custom_error_handler',
... }

Warning

Make sure you always call original global_error_handler in the very end. Unless, you want to disable original error handling.

dmr.errors.wrap_handler(method: _MethodSyncHandler) SyncErrorHandler[source]
dmr.errors.wrap_handler(method: _MethodAsyncHandler) AsyncErrorHandler

Utility function to wrap controller methods.

It is used to wrap an existing controller method and pass it as error_handler= argument to an endpoint.

final class dmr.errors.ErrorType(*values)[source]

Collection of all possible error types that we use in DMR.

value_error

Raised when we can’t parse something.

internal_error

Raised when internal error happens.

not_allowed

Raised when using unsupported http method. 405 alias.

security

Raised when security related error happens.

ratelimit

Raised when ratelimit related error happens.

user_msg

Raised for custom errors from users.

not_found

Raised when we can’t find controller.

streaming

Happens when we stream events.

class dmr.errors.ErrorModel[source]

Default error response schema.

Can be customized. See Customizing error messages for more details.

class dmr.errors.ErrorDetail[source]

Base schema for error details description.

dmr.errors.format_error(error: str | Exception, *, loc: str | list[str | int] | None = None, error_type: str | ErrorType | None = None) ErrorModel[source]

Convert error to the common format.

Default implementation.

Parameters:
  • error – A serialization exception like a validation error.

  • loc – Location where this error happened. Like "headers", or "field_name", or ["parsed_headers", "header_name"].

  • error_type – Optional type of the error for extra metadata.

Returns:

Simple python object - exception converted to a common format.

Problem Details API

class dmr.problem_details.ProblemDetailsError(detail: str, *, status_code: HTTPStatus, type: str | None = None, title: str | None = None, instance: str | None = None, extra: Mapping[str, Any] | None = None, headers: Mapping[str, str] | None = None, cookies: Mapping[str, NewCookie] | None = None, show_status: bool = True, show_detail: bool = True)[source]

Bases: APIError[ProblemDetailsModel]

Problem Details exception.

It is a subclass of dmr.response.APIError, so you can raise it anywhere in the REST part of your app.

There are two major use-cases that we support for this class:

  1. Direct usage: you raise an error and get what you raise, no changes

  2. Conditional usage: you call conditional_error method and if the client accepts application/problem+json, we will return the proper Problem Details description. But, if it is not requested directly, we will return our regular dmr.errors.ErrorModel

Both use-cases are independent. You can decide what to use per controller.

classmethod conditional_error(detail: str, *, status_code: HTTPStatus, controller: Controller[BaseSerializer], type: str | None = None, title: str | None = None, instance: str | None = None, extra: Mapping[str, Any] | None = None, headers: Mapping[str, str] | None = None, cookies: Mapping[str, NewCookie] | None = None, show_status: bool = True, show_detail: bool = True) APIError[Any][source]

Create conditional error.

If request accepts application/problem+json then return a Problem Details exception. If not, return regular dmr.response.APIError instance.

Otherwise, returns regular error from controller using its format_error() method for formatting.

classmethod error_model(existing_errors: Mapping[str, Any], content_type: str | None = None) Any[source]

Builds an error model for conditional responses.

Only use this method when you use conditional_error. If you are using regular exceptions, use ProblemDetailsModel directly.

classmethod format_error(error: str | Exception, *, loc: str | list[str | int] | None = None, error_type: str | ErrorType | None = None, status_code: HTTPStatus | None = None, title: str | None = None, instance: str | None = None, extra: Mapping[str, Any] | None = None) ErrorModel | ProblemDetailsModel[source]

Format other errors to be in format of Problem Details.

class dmr.problem_details.ProblemDetailsModel[source]

Error payload model for Problem Details.

See https://datatracker.ietf.org/doc/html/rfc9457 for the detailed description of each field.