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
bydjango.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 ofget_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, WSGIServer
will 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.
- User requests a page
- Request reaches
Request
Middlewares, which could manipulate or answer the request - The
URLConf
finds the related View usingurls.py
-
View
Middlewares are called, which could manipulate or answer the request - The
view
function is invoked - The
view
could optionally access data through models - All model-to-DB interactions are done via a manager
-
View
s could use a special context if needed - 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
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/
Please log in to upload a file.
There are no updates yet.
Click the Upload button above to add an update.