Skip to content

Request-Response Flow

Django tl;dr

It handles request-response patterns between the client, usually a browser , and an http server

It sources data from auto-generated sql queries, each called a Queryset.

Server-side Views are templates, built with html , css , and js , rendered via browser response.

It goes further by including the kitchen sink, i.e.

  1. orm-sql for many sql engines
  2. dtl/jinja templating language,
  3. seo
  4. rss , etc.
flowchart LR
    subgraph request
        url
    end
    subgraph server
        django
        subgraph batteries
            orm
            dtl
            seo
            rss
        end
    end
    subgraph response
        html
        css
        js
    end
    request--url endpoint--->django--route to view-->response

request to server

We start with a url.

runserver gives us: http://127.0.0.1:8000/.

Opening this url in the browser initiates an HttpRequest to a server.

Dissect Runserver Prompt
The Runserver URL
# This is how a Django project is run locally
python manage.py runserver
# Watching for file changes with StatReloader autoreload.
# Performing system checks...

# System check identified no issues (0 silenced).
# March 01, 2023 - 00:00:00
# Django version 4.2, using settings 'config.settings'
# Starting development server at http://127.0.0.1:8000/
# Quit the server with CONTROL-C.

Let's parse lines 8 and 9:

  1. config.settings implies that, for this particular Django instance, the main project folder is named config.
  2. Django's local development server is running at a specific URL: http://127.0.0.1:8000/
  3. While this is running, I can type the said URL in a browser and hit enter.
  4. I can expect that a HttpRequest will be sent to this running server.
  5. The server receives the request and returns, to the requesting browser, some html, css, and js as an HttpResponse.
  6. This pattern is known as the request-response cycle.
  7. Django will now look for an appropriate urlpattern route that matches the URL.

In local environments, the server is django's runserver. In production environments, a popular choice of server is gunicorn.

server to router + view

Django matches the url endpoint to a developer-defined UrlPattern route.

What is the endpoint? Well, it's the tip of the url. So the router's matching process goes something like this for url http://127.0.0.1:8000/:

  1. 👀 does the endpoint of http://127.0.0.1:8000/ match /about? No.
  2. 👀 does the endpoint of http://127.0.0.1:8000/ match /contact-us? No.
  3. 👀 does the endpoint of http://127.0.0.1:8000/ match /? Yes.
Dissect URL Routing

More technically, if the requested url is http://127.0.0.1:8000/, this represents an empty string "" following the backslash "/". How do we find the matching pattern in the code?

If we look inside the config.settings.base module, there are many variables but our interest is in:

/config/settings/_settings.py
ROOT_URLCONF = "config.urls"

This declares Django's routing system to be controlled by a urls.py file found in the config folder:

See /config/urls.py, the main router
1
2
3
4
5
6
7
8
urlpatterns = [
    ...
    path("accounts/", include("allauth.urls")),
    path("profiles/", include("profiles.urls")),
    path("", TemplateView.as_view(template_name="home.html"), name="home"),
    # match found! in ""
    ...
]

server sends response containing a view

The endpoint / is typically the homepage of the website.

It's up to the developer to construct how this View looks like, typically by combining html, css, and js with data that is persisted in a database.

So the route to / represents a pre-constructed homepage View .

Dissect View Templating

Django offers some class-based views to make displaying content simpler. In this case, we're using a minimal TemplateView (which inherits from View) relying on a certain "home.html". Where do we find this "home.html"?

In our Django config.settings.base module, we determine where to source templates:

Templates Directory
BASE_DIR = Path(__file__).resolve().parent.parent.parent
...
TEMPLATES = [
    {
        "BACKEND": "django.template.backends.django.DjangoTemplates",
        "DIRS": [BASE_DIR / "templates"],  # added
        "APP_DIRS": True,
        "OPTIONS": {
            ...
        },
    },
]
Django Templating Language
1
2
3
4
5
6
7
8
9
{% extends 'base.html' %} <-- home.html is a partial template, its parents is base.html --->
{% block content %}
    <h1>Home</h1>
    <article>
        <p>Sample <mark>text</mark> highlighted for illustration.</p>
        <blockquote>This is a blockquote<br>- <cite>Quoting from a random person</cite></blockquote>
        {% lorem 2 p random %}
    </article>
{% endblock content %}

The content of home.html is what the browser will receive as a response. Although this doesn't look like much, it can contain subtemplates as implied by the very first line. If we look at the refernced "base.html" in Line 1, we can see the full page of "home.html"

In the /templates directory, we see "home.html" which contains the following content:

base.html: see included css, js
{% load static %}
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <meta name="description" content="Sample description "> <!-- # Customize content for search -->
        {% block title %}<title>Test site sample</title> {% endblock title %}<!-- Enable title changes -->
        {% include './_favicons.html' %}
        {% block custom_css %}
            <link rel="stylesheet" href="https://unpkg.com/@picocss/pico@1.*/css/pico.min.css">
            {% block extra_css %}
            {% endblock extra_css %}
        {% endblock custom_css %}
    </head>
    <body class="container">
        {% include './nav.html' %}
        {% include './_messages.html' %}
        {% block body %}
            {% block content %}
            <!-- This is what "home.html" populates -->
            {% endblock content %}
            {% block base_js %}
                <script src="https://unpkg.com/htmx.org@..."></script>
                <script src="https://unpkg.com/hyperscript.org@..."></script>
                <script>document.body.addEventListener("htmx:configRequest", (e) => {e.detail.headers["X-CSRFToken"] = "{{ csrf_token }}";});</script>
                {% block extra_js %}
                {% endblock extra_js %}
            {% endblock base_js %}
        {% endblock body %}
    </body>
</html>

Summary

We started with a requesting url http://127.0.0.1:8000/ and retrieved a viewable response.

  1. The url's endpoint / made an HttpRequest to the server.
  2. server pinged routing and it replied with:

    "Yes, I have a View representing request to endpoint /"

  3. This View is packaged into a HttpResponse for rendering in the browser.

  4. Since the View will likely contain other urls... we can expect more request-response cycles.