Is the Django base logic diagram
The WSGI module is encapsulated in the ①django to loop through the socket link, and when the client sends a Web request, WSGI establishes a connection with the client to send the data.
After the ②socket communication is established, a layer of middleware filtering is experienced before the user requests to enter Django:
The specific process is as follows:
1.process_request
2.peocess_view
3.process_exception
4.process_template_response
5.process_response
Among them 3, 4 links My understanding is mutually exclusive, when appears exception, will not appear in the entire render the page, Process_template_response also will not execute, if appears the rendering page then also means that the exception has not been triggered.
③url is a Django routing match (which behaves as a views.py file in a Djangox project, looking for a corresponding view function with a regular match based on the URL address requested by the user).
Note: Because route matching is a top-down match in the form of a list traversal, if the route matching definition in Chen Xu is not clear, there will be situations where the match is not matched or cannot be matched.
④ when matching the corresponding view function, the dynamic page will get the data from the back-end database, which is appended to the return value in the View function.
⑤ because page rendering is a relatively complex process, so we put the page rendering in template templates, the specific application is the use of template language, in the following blog, will be described in detail, today the main narrative wsgi,middleware,url
One, Wsgi
Create a new Django project, in the project folder, there will be a wsgi.py file.
The code is as follows;
"""
WSGI the config for database to create project.
It exposes the WSGI callable as a module-level variable named ' Application '.
For more information on the this file, see
https://docs.djangoproject.com/en/1.11/howto/deployment/wsgi/
"""
Import OS
From Django.core.wsgi import get_wsgi_application
Os.environ.setdefault ("Django_settings_module", "Database creation. SETTINGS")
Get_wsgi_application ()
This is a function of the Django internal definition, CTRL + Left click to enter the function
Def get_wsgi_application ():
"""
The public interface to Django's WSGI support. Should return a WSGI
Callable.
Allows us to avoid making django.core.handlers.WSGIHandler public API, in
Case the internal WSGI implementation changes or moves in the future.
"""
Django.setup (Set_prefix=false)
Wsgihandler ()
we notice that the return value is Wsgihandler ()
Continue Ctrl + Left click to enter
class Wsgihandler (base. Basehandler):
Request_class = Wsgirequest
def __init__ (self, *args, **kwargs):
Super (Wsgihandler, self). __init__ (*args, **kwargs)
Self.load_middleware ()
def __call__ (self, Environ, start_response):
Set_script_prefix (Get_script_name (environ))
Signals.request_started.send (sender=self.__class__, Environ=environ)
Request = Self.request_class (environ)
Response = Self.get_response (Request)
Response._handler_class = self.__class__
Status = '%d%s '% (Response.status_code, response.reason_phrase)
Response_headers = [(str (k), str (v)) for K, V in Response.items ()]
For C in Response.cookies.values ():
Response_headers.append ((str (' Set-cookie '), str (c.output (header= '))))
Start_response (Force_str (status), Response_headers)
If GetAttr (response, ' File_to_stream ', none) is not None and Environ.get (' Wsgi.file_wrapper '):
Response = environ[' Wsgi.file_wrapper '] (response.file_to_stream)
return response
Before we look at his father, we go first.Request_class = wsgirequest
Class Wsgirequest (HTTP. HttpRequest):
We can see that this is another inherited class.
Never die, go into this class (HTTP. HttpRequest)
class HttpRequest (object):
"" "A basic HTTP request." "
# The encoding used in Get/post dicts. None means use default setting.
_encoding = None
_upload_handlers = []
def __init__ (self):
# warning:the ' wsgirequest ' subclass doesn ' t call ' super '.
# any variable assignment made this should also happen in
# ' wsgirequest.__init__ () '.
Self . GET = Querydict (mutable=true)
Self . POST = Querydict (mutable=true)
Self . COOKIES = {}
Self . META = {}
Self . FILES = Multivaluedict ()
Self.path = ' '
self.path_info = ' '
Self.method = None
Self.resolver_match = None
self._post_parse_error = False
Self.content_type = None
self.content_params = None
At this point we have basically can see we request the head of some information, this is we give Wsgi some request header information, finally, we found the comparison of the original socket connection part, open not happy, excited?
Wsgihandler is a Django-defined class (this class inherits Base.basehandler), the usual, click into the parent class
Because the parent class code is too long, here I only intercept the basic information of the parent class plus the text comment
Basehandler (object):
def __init__ (self):
Self._request_middleware = None
Self._view_middleware = None
Self._template_response_middleware = None
Self._response_middleware = None
Self._exception_middleware = None
Self._middleware_chain = None
def load_middleware (self):
This function mainly reads the middleware information in the settings configuration file and executes the corresponding middleware functions using the reflection of the class.
Actually, from the execution of these two classes, we can basically see the order in which the Django program executes.
Signal in the beginning of the program, the listening state is turned on, which is why we wrote the custom signal to write in the __init__ file, because the signal listener should be reflected in the program's entire life cycle of the
request variable initialization, This is the variable we use when we send a request, and he encapsulates most of the information in our Web request. The use of
cookies, in the early stages of the program, we use cookies to record the identity bits we visit each time
All the magical variables we use in Django are all in our magical class.
OK, next we talk about middleware!
Because our settings configuration file is a string-formatted middleware, we can copy a string and introduce it in his path, so we can see how the original Django middleware was defined
Here I find a random middleware to do the experiment ha.
From django.middleware.security import Securitymiddleware
Middleware = [
' Django.middleware.security.SecurityMiddleware ',
' Django.contrib.sessions.middleware.SessionMiddleware ',
' Django.middleware.common.CommonMiddleware ',
' Django.middleware.csrf.CsrfViewMiddleware ',
' Django.contrib.auth.middleware.AuthenticationMiddleware ',
' Django.contrib.messages.middleware.MessageMiddleware ',
' Django.middleware.clickjacking.XFrameOptionsMiddleware ',
]
See how I got the import? Very simple Oh, haha
Let's go inside and see what he really is.???
class Securitymiddleware (middlewaremixin):
def __init__ (self, Get_response=none):
Self.sts_seconds = settings. Secure_hsts_seconds
Self.sts_include_subdomains = settings. Secure_hsts_include_subdomains
Self.sts_preload = settings. Secure_hsts_preload
Self.content_type_nosniff = settings. Secure_content_type_nosniff
Self.xss_filter = settings. Secure_browser_xss_filter
Self.redirect = settings. Secure_ssl_redirect
Self.redirect_host = settings. Secure_ssl_host
Self.redirect_exempt = [Re.compile (r) for r in Settings. Secure_redirect_exempt]
Self.get_response = Get_response
def process_request (self, request):
Path = Request.path.lstrip ("/")
if (Self.redirect and not request.is_secure () and
Not any (Pattern.search (path)
For pattern in self.redirect_exempt)):
Host = Self.redirect_host or Request.get_host ()
Return Httpresponsepermanentredirect (
"https://%s%s"% (host, Request.get_full_path ())
)
def process_response (self, request, response):
if (Self.sts_seconds and request.is_secure () and
' Strict-transport-security ' not in response):
Sts_header = "max-age=%s"% self.sts_seconds
If Self.sts_include_subdomains:
Sts_header = Sts_header + "; Includesubdomains "
If Self.sts_preload:
Sts_header = Sts_header + "; Preload "
response["strict-transport-security"] = Sts_header
If Self.content_type_nosniff and ' x-content-type-options ' not in response:
response["x-content-type-options"] = "Nosniff"
If Self.xss_filter and ' x-xss-protection ' not in response:
response["x-xss-protection"] = "1; Mode=block "
return response
Of course, this is another inherited class, so let's go and see his parent class.
Class Middlewaremixin (object):
def __init__ (self, Get_response=none):
Self.get_response = Get_response
Super (Middlewaremixin, self). __init__ ()
def __call__ (self, request):
Response = None
If hasattr (self, ' process_request '):
Response = self.process_request (Request)
If not response:
Response = Self.get_response (Request)
If hasattr (self, ' process_response '):
Response = Self.process_response (Request, response)
return response
At this point, I intend to use my most superficial understanding to tell about our middleware, on the basis of inheriting the Middlewaremixin parent class, we define a class ourselves, we should pay attention to which part of our custom middleware wants to limit
In which section we define our class methods:
1.process_request
2.peocess_view
3.process_exception
4.process_template_response
5.process_response
You can define these five ways, if you just want a good look, then OK, just write the pass in the function body.
In addition, where does the middleware need to be defined? The answer is where to write where to write? As long as you introduce the middleware class py file into the setting configuration file, and add one or more strings to your settings.
Is it particularly convenient and simple?
Oh, next is the URL
So, open the urls.py file in Django and let's analyze it.
From Django.conf.urls import URL
From Django.contrib Import admin
From database. Views Import *
Urlpatterns = [
URL (r ' ^admin/', admin.site.urls),
URL (r ' ^add/', add),
]
The simplest understanding is to iterate over the urlpatterns and match the URL address that the client requested by matching the regular matching string, matching it to the corresponding view function.
But in order to be responsible for themselves, or analysis, although it is only homework.
Click Gold to enter the URL
def url (regex, view, Kwargs=none, Name=none):
If isinstance (view, (list, tuple)) :
# for include (...) processing.
urlconf_module, app_name, namespace = view
Return Regexurlresolver (Regex, Urlconf_module, Kwargs, App_name=app_name, namespace=namespace)
Elif cal lable (view):
return regexurlpattern (Regex, view, Kwargs, name) else:
Raise TypeError (' View must is a callable or a list/tuple in the case of include (). ')
We can see that there are two fixed positional parameters. One is a regular match expression, and the other is the corresponding view function.
Note that at this point we match the view parameter is to be in the form of a list or a tuple to get, when the match will be separated by itself, then our final function body is Which???
After my thinking, he is namespace, is not a very familiar name, namespace, we know each of the Python variables, each Han Shuming, each column name, is stored in our namespace, through the relationship mapping, we
can find his corresponding value, thus executing our function body, get the final result.
Perhaps everyone also notice, I purple mark of content, this is another class, not, my lazy cancer again committed, today will not write, haha
Django (Wsgi,middleware,url source profiling)