Django 生命周期涉及知识点一网打尽 第一篇

1. 简述Http协议?
    - 超文本传输协议
        - 特点:
            - 无状态,请求响应之后,再次发起请求时,不认识。
            - 短连接,一次请求和一次响应就断开连接。
        - 格式:
        
            - GET请求:输入地址回车:https://passport.jd.com/new/login.aspx?ReturnUrl=https%3A%2F%2Fwww.jd.com%2F
                请求由两部分组成:请求头和请求体,请求头和请求体通过\r\n\r\n分割,请求头和请求头之间通过\r\n分割。
                    """GET /new/login.aspx?ReturnUrl=https%3A%2F%2Fwww.jd.com%2F http1.1\r\nUser-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36\r\nHost:jd.com\r\n\r\n"""
                响应由两部分组成:响应头和响应体,
                    b'HTTP/1.1 200 OK\r\nDate: Mon, 05 Nov 2018 01:15:31 GMT\r\nServer: Apache\r\nLast-Modified: Tue, 12 Jan 2010 13:48:00 GMT\r\nETag: "51-47cf7e6ee8400"\r\nAccept-Ranges: bytes\r\nContent-Length: 81\r\nCache-Control: max-age=86400\r\nExpires: Tue, 06 Nov 2018 01:15:31 GMT\r\nConnection: Keep-Alive\r\nContent-Type: text/html\r\n\r\n <html><head> .... </html>'
                    
            - POST请求:
                请求由两部分组成:请求头和请求头
                    """POST /new/login.aspx?ReturnUrl=https%3A%2F%2Fwww.jd.com%2F http1.1\r\nUser-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36\r\nHost:jd.com\r\n\r\nusername=haoxu666&password=123"""
                响应:
                    b'HTTP/1.1 200 OK\r\nDate: Mon, 05 Nov 2018 01:15:31 GMT\r\nServer: Apache\r\nLast-Modified: Tue, 12 Jan 2010 13:48:00 GMT\r\nETag: "51-47cf7e6ee8400"\r\nAccept-Ranges: bytes\r\nContent-Length: 81\r\nCache-Control: max-age=86400\r\nExpires: Tue, 06 Nov 2018 01:15:31 GMT\r\nConnection: Keep-Alive\r\nContent-Type: text/html\r\n\r\n用户名或密码错误'
                    
2. 你了解的请求头都有什么?
    - User-Agent,设备信息。
    - Host,当前访问的主机名称。
    - referrer,做防盗链。
    - Content-Type: ....
    
3. 你了解的请求方式有哪些?
    - GET/POST/PUT/PATCH/DELETE/OPTIONS 
    
4. django请求的生命周期/浏览器上输入 http://www.oldboyedu.com 地址回车发生了什么?
    
    - 浏览器输入:http://www.oldboyedu.com 回车
    - DNS解析,将域名解析成IP。
    - 浏览器(socket客户端),根据IP和端口(80)创建连接,发送请求。
    - 服务端接收请求
        - 实现了wsgi协议的模块,如:wsgiref接收到用户请求。
        - 然后将请求转交给django的中间件,执行中间件的process_request(process_view)。
        - 路由系统进行路由匹配。
        - 匹配成功执行视图函数,视图函数进行业务处理(ORM操作数据+模板渲染)
        - 交给中间件的process_response方法
        - wsigref的socket.send,将结果返回给浏览器。
        - 断开socket连接。
    - 浏览器断开连接。
    
    详细:见django请求生命周期图
        
5. 什么是wsgi?
    wsgi,web服务网关接口,他是一套协议。
    实现wsgi协议有:
        - wsgiref 
        - uwsgi 
    实现wsgi协议的所有的模块本质:socket服务端。
    
6. django中间件的作用?应用场景?
    中间件,可以对所有请求进行批量操作。
    应用场景:
        - 自己玩
            - 记录日志
            - IP黑名单
        
        - 权限系统中的权限校验
        - 解决跨域:编写一个中间件,在中间件中定义一个process_response,添加一个响应头(CORS,跨站资源共享)
        - 用户登录 
        - csrf_token验证(django内置功能)
    细节:
        - 5个方法:process_request/process_response + 3 
        - 执行流程 
            正常流程:
                - 所有process_request 
                - 所有process_view 
                - 所有process_response 
            非正常流程:
                - django 1.10及以后:平级返回
                - django 1.10以前:找到最后的process_response 
        
        - 写代码时,如果忘记方法名称或方法参数个数,怎么办?
            - 任意导入一个源码查看,如:
                # from django.middleware.common import CommonMiddleware
                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',
                ]
        - 执行流程是如何实现的?
            将中间件的相关方法添加到对应的 5个列表中,以后循环执行(顺序、倒序)
            源码:
                class 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):
                        """
                        Populate middleware lists from settings.MIDDLEWARE (or the deprecated
                        MIDDLEWARE_CLASSES).

                        Must be called after the environment is fixed (see __call__ in subclasses).
                        """
                        self._request_middleware = []
                        self._view_middleware = []
                        self._template_response_middleware = []
                        self._response_middleware = []
                        self._exception_middleware = []

                        if settings.MIDDLEWARE is None:
                            warnings.warn(
                                "Old-style middleware using settings.MIDDLEWARE_CLASSES is "
                                "deprecated. Update your middleware and use settings.MIDDLEWARE "
                                "instead.", RemovedInDjango20Warning
                            )
                            handler = convert_exception_to_response(self._legacy_get_response)
                            for middleware_path in settings.MIDDLEWARE_CLASSES:
                                mw_class = import_string(middleware_path)
                                try:
                                    mw_instance = mw_class()
                                except MiddlewareNotUsed as exc:
                                    if settings.DEBUG:
                                        if six.text_type(exc):
                                            logger.debug('MiddlewareNotUsed(%r): %s', middleware_path, exc)
                                        else:
                                            logger.debug('MiddlewareNotUsed: %r', middleware_path)
                                    continue

                                if hasattr(mw_instance, 'process_request'):
                                    self._request_middleware.append(mw_instance.process_request)
                                if hasattr(mw_instance, 'process_view'):
                                    self._view_middleware.append(mw_instance.process_view)
                                if hasattr(mw_instance, 'process_template_response'):
                                    self._template_response_middleware.insert(0, mw_instance.process_template_response)
                                if hasattr(mw_instance, 'process_response'):
                                    self._response_middleware.insert(0, mw_instance.process_response)
                                if hasattr(mw_instance, 'process_exception'):
                                    self._exception_middleware.insert(0, mw_instance.process_exception)
                        else:
                            handler = convert_exception_to_response(self._get_response)
                            for middleware_path in reversed(settings.MIDDLEWARE):
                                middleware = import_string(middleware_path)
                                try:
                                    mw_instance = middleware(handler)
                                except MiddlewareNotUsed as exc:
                                    if settings.DEBUG:
                                        if six.text_type(exc):
                                            logger.debug('MiddlewareNotUsed(%r): %s', middleware_path, exc)
                                        else:
                                            logger.debug('MiddlewareNotUsed: %r', middleware_path)
                                    continue

                                if mw_instance is None:
                                    raise ImproperlyConfigured(
                                        'Middleware factory %s returned None.' % middleware_path
                                    )

                                if hasattr(mw_instance, 'process_view'):
                                    self._view_middleware.insert(0, mw_instance.process_view)
                                if hasattr(mw_instance, 'process_template_response'):
                                    self._template_response_middleware.append(mw_instance.process_template_response)
                                if hasattr(mw_instance, 'process_exception'):
                                    self._exception_middleware.append(mw_instance.process_exception)

                                handler = convert_exception_to_response(mw_instance)

                        # We only assign to this when initialization is complete as it is used
                        # as a flag for initialization being complete.
                        self._middleware_chain = handler
        
        - 根据字符串的形式导入模块 + 根据反射找到模块中的成员
            
    
    总结:
        特点:
            - 所有请求都要通过中间件
            - 5个方法
            - 5个方法的执行流程
                - 正常
                - 不正常(版本区别)
            
        应用场景:
            - 自己玩:
                - IP黑名单限制
                - 日志
            - 工作场景:
                - 权限控制
                - 跨域
                - 登录
                - CSRF
        
        相关知识点:
            - 流程实现原理:列表+列表翻转
            - 根据字符串的形式导入模块+反射
                

            
7. 路由系统 
    本质:保存url和函数的对应关系。
    相关知识点: 
        示例1:
            url(r'^index/', views.index),
            
            def index(request):
                return HttpResponse('...')

        示例2:
            url(r'^user/edit/(\d+)/$', views.user_edit),
            
            def user_edit(request,nid):
                return HttpResponse('...')

        示例3:
            url(r'^crm/', include('app01.urls'))
                
            from django.conf.urls import url,include
            from app01 import views
            urlpatterns = [
                url(r'^order/', views.order),
                url(r'^center/', views.center),
            ]

            def order(request):
                return HttpResponse('...')

            def center(request):
                return HttpResponse('...')
    
        示例4:根据name别名反向生成URL
            urlpatterns = [
                url(r'^admin/', admin.site.urls),
                url(r'^index/', views.index,name='index'),
                url(r'^user/edit/(\d+)/$', views.user_edit,name='user_edit'),
                url(r'^crm/', include('app01.urls')),
            ]
        
                urlpatterns = [
                    url(r'^order/', views.order,name='order'),
                    url(r'^center/', views.center,name='center'),
                ]
                    
            
            反向生成:
                
                index_url = reverse('index')
                user_edit_url = reverse('user_edit',args=('999',))
                
                index_url = reverse('order')
                index_url = reverse('center')
        
        示例5:根据 namespace + name 别名反向生成URL
            urlpatterns = [
                url(r'^admin/', admin.site.urls),
                url(r'^index/', views.index,name='index'),
                url(r'^user/edit/(\d+)/$', views.user_edit,name='user_edit'),
                url(r'^crm/', include('app01.urls',namespace='crm')),
            ]
        
                urlpatterns = [
                    url(r'^order/', views.order,name='order'),
                    url(r'^center/', views.center,name='center'),
                ]
                    
            
            视图中反向生成:
                
                index_url = reverse('index')
                user_edit_url = reverse('user_edit',args=('999',))
                
                index_url = reverse('crm:order')
                index_url = reverse('crm:center')
                
            在模板中反向生成:
                
                {% url 'index' %}
                {% url 'user_edit' 999 %}
                
                {% url 'crm:order' %}
                {% url 'crm:center' %}

            
    补充:公司项目从路由开始看,可能你看到的是这样。
        urlpatterns = [
            url(r'^admin/', admin.site.urls),
            url(r'^index/', views.index,name='index'),
            url(r'^user/edit/(\d+)/$', views.user_edit,name='user_edit'),
            url(r'^crm/', include('app01.urls',namespace='crm')),
        ]


        urlpatterns += [
            url(r'^xxxx/', views.index),
        ]


8. 什么是MVC、MTV?
    
    MVC, Model View   Controller
    
    MTV, Model Template  View 

9. FBV和CBV
    FBV,写函数进行处理业务逻辑。
    CBV,写类进行处理业务逻辑。
    
    本质上FBV和CBV都是一样的,因为url对应都是一个函数。
        url(r'^order/', views.order,name='order'), # 1. 对应order函数;2.一旦请求到来,立即执行order函数
        url(r'^center/', views.CenterView.as_view(),name='center'), # 1. url对应 views.CenterView.as_view()会返回一个view函数;2. 请求到来之后,立即执行view函数,view由会触发dispatch方法、dispatch会根据method不同根据反射执行get/post/delete...的方法。
    
    推荐:
        业务逻辑,FBV(简单)。
        restful api,CBV。
        
10. 现象:两个系统之间进行相互数据传输,李超向讲师机发送POST请求,但讲师机的request.POST中没有获取到数据,可能是因为什么?
    
    1. csrf_token 
        from django.views.decorators.csrf import csrf_exempt,csrf_protect

        @csrf_exempt
        def api(request):
            """
            为李超提供的API接口
            :param request:
            :return:
            """
            print(request.POST)
            return HttpResponse('...')
            
            
        实例代码:
            李超.py:
                import requests
                response = requests.post('http://127.0.0.1:8000/crm/api/',data={'user':'alex','pwd':'dsb'})
                print(response.text)
                
                Http请求格式:
                    """POST /crm/api/ http\1.1\r\nhost:..\r\nContent-Type:application/x-www-form-urlencoded .....\r\n\r\nuser=alex&pwd=dsb"""
                
                
            django服务端:
                
                from django.views.decorators.csrf import csrf_exempt,csrf_protect

                @csrf_exempt
                def api(request):
                    """
                    为李超提供的API接口
                    :param request:
                    :return:
                    """
                    print(request.POST)
                    return HttpResponse('...')

                
    2. request.POST解析时,有限制。
    
            李超.py 
    
                import requests
                response = requests.post('http://127.0.0.1:8000/crm/api/',json={'user':'alex','pwd':'dsb'})
                print(response.text)
                
                Http请求格式:
                    """POST /crm/api/ http\1.1\r\nhost:..\r\nContent-Type:application/json .....\r\n\r\n{'user':'alex','pwd':'dsb'}"""
                
            django服务端:    
                @csrf_exempt
                def api(request):
                    """
                    为李超提供的API接口
                    :param request:
                    :return:
                    """
                    print(request.body) # 原生的请求体格式,有数据;(自己读取body然后进行解析)
                    print(request.POST) # 将原生的请求体转换成 QueryDict对象,无数据。
                    return HttpResponse('...')

            
            注意:
                request.POST 将原生的请求体转换成 QueryDict对象,请求必须满足两个条件才能转换:
                    - Content-Type:application/x-www-form-urlencoded
                    - 数据格式: user=alex&pwd=dbs&xxx=123 
                    
                如果不满足此条件,django获取请求体时需要自己去request.body中获取值。
                
    
    总结:
        django获取请求体 request.body 
        request.POST是将请求体的数据转换成了QueryDict对象。
        
    
11. 视图函数的返回值 
    
    HttpResponse 
    render 
        示例1:
            视图:
                def test(request):
                    """
                    :param request:
                    :return:
                    """
                    return render(request,'test.html',{'k1':123})
                    
            test.html 
                <!DOCTYPE html>
                <html lang="en">
                <head>
                    <meta charset="UTF-8">
                    <meta http-equiv="x-ua-compatible" content="IE=edge">
                    <meta name="viewport" content="width=device-width, initial-scale=1">
                    <title>Title</title>
                </head>
                <body>
                <div>
                    <h1>{{ k1 }}</h1>
                    <script>
                        alert('{{ k1 }}');
                    </script>
                </div>
                </body>
                </html>
        示例2: 
            视图:
                def test(request):
                    """
                    :param request:
                    :return:
                    """
                    return render(request,'test.html',{'k1':123})
                    
            test.html 
                <!DOCTYPE html>
                <html lang="en">
                <head>
                    <meta charset="UTF-8">
                    <meta http-equiv="x-ua-compatible" content="IE=edge">
                    <meta name="viewport" content="width=device-width, initial-scale=1">
                    <title>Title</title>
                </head>
                <body>
                <div>
                    <h1>{{ k1 }}</h1>
                    <script src='/static/commons.js'></script>
                </div> 
                </body>
                </html>
                
            commons.js 
                alert('{{k1}}')
                
    redirect 
        将要重定向的地址通过响应头Location响应头返回给浏览器。

猜你喜欢

转载自www.cnblogs.com/pupilheart/p/9910859.html
今日推荐