Some insights into the low-level workflow of the Django framework

How does Django run

There are many ways to run a Django app, one of which is runserver which uses the web server of Django itself, and it is mostly used in the development and testing phases. Another is using protocols like fastcgi and uWSGI…


This content originally appeared on DEV Community and was authored by Angelo H

How does Django run

There are many ways to run a Django app, one of which is runserver which uses the web server of Django itself, and it is mostly used in the development and testing phases. Another is using protocols like fastcgi and uWSGI.

1. runserver

Usage: python3 manage.py runserver, this command is run under port 8080 by default. If you investigate into the source codes of manage.py, you will find that this command is actually executed through the internal runserver command in execute_from_command_line, and this command mostly does two things:

  • Parse the parameters, and get the wsgi handler by django.core.servers.basehttp.get_internal_wsgi_application;
  • Generate a WSGIServer object according to your IP address and port, and then accept the user's requests. The source codes of get_internal_wsgi_application is as followed:
def get_internal_wsgi_application():
    """
    Loads and returns the WSGI application as configured by the
    user in ``settings.WSGI_APPLICATION``. With the default   
    ``startproject`` layout, this will be the ``application`` object in ``projectname/wsgi.py``.
    This function, and the ``WSGI_APPLICATION`` setting itself, are     
    only useful for Django's internal servers (runserver, runfcgi); 
    external WSGI servers should just be configured to point to the 
    correct application object directly.
    If settings.WSGI_APPLICATION is not set (is ``None``), we just   
    return whatever ``django.core.wsgi.get_wsgi_application`` returns.
    """
    from django.conf import settings
    app_path = getattr(settings, 'WSGI_APPLICATION')
    if app_path is None:
        return get_wsgi_application()
    return import_by_path(
        app_path,
        error_prefix="WSGI application '%s' could not be loaded; " % app_path
    )

By the above source codes we know that, Django will first obtain the handler via WSGI_APPLICATION in settings. While building the project, Django will create a wsgi.py by default.

2. uWSGI

uWSGI+Nginx approach is the most prevalent one while running Django in production. To dive more deeply into this method, we would need to learn more about WSGI and uWSGI protocal.

  • WSGI is short for Web Server Gateway Interface, or Python Web Server Gateway Interface. It is a simple and universally applicable interface that bridges python-based web servers and web apps/framworks, and is designed based on the current CGI standard. WSGI is actually a gateway, which helps conversion between multiple protocols.
  • uWSGI is a web server which supports protocols like WSGI protocol, UWSGI protocol and HTTP Protocol, etc. It is known for rapid transmission, low memory usage and its excellence in multi-app management.

HTTP Request Process

Django's RESTful workflow is similar to other web frameworks: Receiving requests and returning responses. Let's see the details in the following:

When Django is creating the project via django-admin, it will automatically create some default files including settings.py and manage.py, and execute the following command before building the WSGIServer:

from django.conf import settings

During the execution of the above command, Django will read the DjANGO_SETTINGS_MODULE config info in os.environ and load the config files before creating the setting object. Therefore, inside the manage.py, it will first add the path of project settings to the os path before obtaining the WSGIServer.

1. Creating the WSGIServer

No matter you are running your Django project with runserver or uWSGI, Django will always call run() in django.core.servers.basehttp during the start-up, creating an instance of django.core.servers.basehttp.WSGIServer, and later call its serve_forever() to start the HTTP services. Below is the source codes of run():

 def run(addr, port, wsgi_handler, ipv6=False, threading=False):
     server_address = (addr, port)
     if threading:
        httpd_cls = type(str('WSGIServer'), (socketserver.ThreadingMixIn, WSGIServer), {})
    else:
        httpd_cls = WSGIServer
        httpd = httpd_cls(server_address, WSGIRequestHandler, ipv6=ipv6)
        # Sets the callable application as the WSGI application that will receive requests
        httpd.set_app(wsgi_handler)
        httpd.serve_forever()

From the above, we see that: While creating the WSGIServer instance, WSGIRequestHandler is used to designate the HTTP request handler. When the user's request arrives at the server, WSGIServerwill create a WSGIRequestHandler instance, using its handler function to process the http request, and actually in the end it calls run() in wsgiref.handlers.BaseHandler. With set_app(), WSGIServer set up a callable object as an application. The above mentioned handler function will call this application to process the request and return the response. Besides, WSGIServer inherits from wsgiref.simple_server.WSGIServer, but WSGIRequestHandler inherits from wsgiref.simple_server.WSGIRequestHandler, wsgiref is the reference implementation of WSGI from the Python standard library.

2. Process the request

In Django, the aforementioned application is in general an object of django.core.handlers.wsgi.WSGIHandler. WSGIHandler inherits from django.core.handlers.base.BaseHandler and it creates a WSGIRequest instance which further inherits from http.HttpRequest. These are the essenial logics on how Django processes the request.

3. Return the response

There is a get_response method in BaseHandler which will first load the ROOT_URLCONF in the Django project and then find out corresponding view methods or classes according to the url rules. The logics in the view functions/classes will create and return specific responses through the request instance.

After Django returns the results, the run() in wsgiref.handlers.BaseHandler will call finish_response to end the request, and return the contents to the user.

Image description

Image description

  1. User requests a page
  2. Request reaches Request Middlewares, which could manipulate or answer the request
  3. The URLConf finds the related View using urls.py
  4. View Middlewares are called, which could manipulate or answer the request
  5. The view function is invoked
  6. The view could optionally access data through models
  7. All model-to-DB interactions are done via a manager
  8. Views could use a special context if needed
  9. The context is passed to the Template for rendering

a. Template uses Filters and Tags to render the output
b. Output is returned to the view
c. HTTPResponse is sent to the Response Middlerwares
d. Any of the response middlewares can enrich the response or return a completely new response
e. The response is sent to the user’s browser.

A few most important components in these procedures are: Middleware, URLConf and Template, and below we will briefly walk through them.

Middleware

Middleware does not exclusively belong to Django, but also exist in other web frameworks. In Django, middleware could participate in 4 stages in the RESTful process: request, view, response, exception. Accordingly, every class of middleware has the following 4 methods: process_request, process_view, process_response and process_exception. You can define one or more of these methods depending on which stage you want the middleware to put effect on, and every method returns a response object.

URLConf

If none of the middleware that processes the request directly returns a response, then Django will parse the URL requested by the user. URLconf is the mapping of the websites supported by Django. Basically, it is a mapping table between the URL pattern and the view functions. In this way, Django will know which code blocks to call for which urls. Specifically, there is a ROOT_URLCONF constant in the configuration file of the Django project. This constant is added with the root directory "/" as a parameter to create an instance of django.core.urlresolvers.RegexURLResolver, and then parse the URL requested by the user through its resolve method, finding the first matching view.

Template

Most web frameworks have their own Template system, and so does Django. However, the Django template is different from the Mako template and the jinja2 template. You cannot write Python code directly in the Django template. It can only be implemented by additional filters and template tags.

References

[1] https://hitesh.in/2009/django-flow/
[2] https://stackoverflow.com/questions/1836627/diagrams-explanations-of-django-request-processing
[3] https://docs.djangoproject.com/en/3.2/topics/http/urls/
[4] https://docs.djangoproject.com/en/3.2/topics/http/middleware/
[5] https://docs.djangoproject.com/en/3.2/topics/templates/
[6] https://medium.com/@jvdali966/understanding-djangos-work-flow-1ee521422092


This content originally appeared on DEV Community and was authored by Angelo H


Print Share Comment Cite Upload Translate Updates
APA

Angelo H | Sciencx (2021-12-10T03:42:55+00:00) Some insights into the low-level workflow of the Django framework. Retrieved from https://www.scien.cx/2021/12/10/some-insights-into-the-low-level-workflow-of-the-django-framework/

MLA
" » Some insights into the low-level workflow of the Django framework." Angelo H | Sciencx - Friday December 10, 2021, https://www.scien.cx/2021/12/10/some-insights-into-the-low-level-workflow-of-the-django-framework/
HARVARD
Angelo H | Sciencx Friday December 10, 2021 » Some insights into the low-level workflow of the Django framework., viewed ,<https://www.scien.cx/2021/12/10/some-insights-into-the-low-level-workflow-of-the-django-framework/>
VANCOUVER
Angelo H | Sciencx - » Some insights into the low-level workflow of the Django framework. [Internet]. [Accessed ]. Available from: https://www.scien.cx/2021/12/10/some-insights-into-the-low-level-workflow-of-the-django-framework/
CHICAGO
" » Some insights into the low-level workflow of the Django framework." Angelo H | Sciencx - Accessed . https://www.scien.cx/2021/12/10/some-insights-into-the-low-level-workflow-of-the-django-framework/
IEEE
" » Some insights into the low-level workflow of the Django framework." Angelo H | Sciencx [Online]. Available: https://www.scien.cx/2021/12/10/some-insights-into-the-low-level-workflow-of-the-django-framework/. [Accessed: ]
rf:citation
» Some insights into the low-level workflow of the Django framework | Angelo H | Sciencx | https://www.scien.cx/2021/12/10/some-insights-into-the-low-level-workflow-of-the-django-framework/ |

Please log in to upload a file.




There are no updates yet.
Click the Upload button above to add an update.

You must be logged in to translate posts. Please log in or register.