django初识1

django

django初识

django的本质就是基于socket通信

一。127.0.0.1 本地回环地址 后面:8001是端口号 /ppt是根目录下的ppt子网页
二。/当前网站的客户端(根目录)
例如:
127.0.0.1/#默认80可以不写

web框架的功能;

1.使用socket收发信息
2.根据不同路径返回不同的内容
3. 返回动态的数据(字符串的替换 模板的渲染)

1569286224080

web框架的几个开源版本

low版web框架

import socket
server=socket.socket()

server.bind(('127.0.0.1',8001))
server.listen()

while 1:
    conn,addr=server.accept()

    from_brower_msg=conn.recv(1024)
    path=from_brower_msg.decode('utf-8').split(' ')[1]#对收到消息编码转换成字符串,切割成列表【0】是方法【1】是对应的页面
#GET / HTTP/1.1
    #/是本页面的主页面 /后面的home page什么的都是对应的子页面
    print(path)
    conn.send(b'http/1.1 200 ok\r\n\r\n')
    if path=='/':#读取文件都用rb
        with open("04test.html",'rb')as f:
            data=f.read()
    elif path=='/style.css':#判断路径是否存在
        with open('style.css','rb')as f:
            data=f.read()
    elif path == '/mi.png':#每遇到一个url都会请求一次
        with open('mi.png', 'rb') as f:
            data = f.read()
    elif path=="./test.js":
        with open("test.js","rb")as f:
            data=f.read()
    conn.send(data)
    conn.close()

html页面

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link rel="stylesheet" href="./style.css"><!--从上往下执行 遇到io(地址主动向服务端发送请求)-->
</head>
<body>
<h2>24期官网</h2>
<div>
    <img src="./mi.png" alt=""><!--从上往下执行 遇到io(地址主动向服务端发送请求)-->
</div>
<script src="test.js"></script><!--从上往下执行 遇到io(地址主动向服务端发送请求)-->
</body>

</html>

只要跳出html文件就会出问题

升级函数版多线程

import socket
from concurrent.futures import ThreadPoolExecutor

server=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
server.bind(("127.0.0.1",8848))
server.listen()

#一定记得关闭连接 等待下一个连接请求
#处理页面请求的函数
def home(conn):
    with open('04test.html','rb')as f:
        data=f.read()
        conn.send(data)
        conn.close()#关闭连接等待下一个请求
#处理页面link( <link rel="stylesheet" href="test.css">)标签href属性值是本地路径的时候的请求        
def css(conn):
    with open('style.css','rb')as f:
        data=f.read()
        conn.send(data)
        conn.close()#关闭连接
#处理页面script(<script src="test.js"></script>)标签src属性值是本地路径的时候的请求
def js(conn):
    with open("test.js","rb")as f:
        data=f.read()
        conn.send(data)
        conn.close()

#处理页面img标签src属性值是本地路径的时候的请求

def pic(conn):
    with open("mi.png","rb")as f:
        data=f.read()
        conn.send(data)
        conn.close()#关闭
while 1:
    conn,addr=server.accept()
    from_brower_msg = conn.recv(1024)
    # print(from_brower_msg)
    path = from_brower_msg.decode('utf-8').split(' ')[1]
    print(path)
    conn.send(b'HTTP/1.1 200 ok\r\n\r\n')
    urlpatterns = [
        ('/',home),
    ('/style.css',css),
    ('/test.js',js),
    ('/mi.png',pic)
    ]
    #线程池
    for url in urlpatterns:
        if path ==url[0]:
            # ret=url)[1](
            t=ThreadPoolExecutor()#开启一个线程池
            t.submit(url[1],conn)#
            break
      else:
        conn.send(b'404')
 ············································       #多线程
    for url in urlpatterns:
        if path == url[0]:
           t = Thread(target=url[1],args=(conn,))
            t.start()
            break
    else:
        conn.send(b'404')

jinja2 第三方内置框架和wsgiref类似socketserver

jinja2 (浏览器渲染)本质是字符串替换

把数据库中查询到的内容进行文本的替换,读取用r

字符串替换replace

用jinja2独有的渲染方法 flask 里面的东西 没有渲染 利用jinja2渲染

wsgiref和jinja

from wsgiref.simple_server import make_server
from jinja2 import Template


def index():
   # 把数据库中查询到的内容进行文本的替换,读取用r 
    with open("index2.html", "r",encoding='utf-8') as f:
        data = f.read()
    template = Template(data)  # 生成模板文件
    ret = template.render({"name": "于谦", "hobby_list": ["烫头", "泡吧"]})  # 把数据填充到模板里面
    return [bytes(ret, encoding="utf8"), ]


# 定义一个url和函数的对应关系
URL_LIST = [
    ("/index/", index),
]
#environ返回的是一个字典
def run_server(environ, start_response):
    start_response('200 OK', [('Content-Type', 'text/html;charset=utf8'), ])  # 设置HTTP响应的状态码和头信息
    url = environ['PATH_INFO']  # 取到用户输入的url
    func = None  # 将要执行的函数
    for i in URL_LIST:
        if i[0] == url:
            func = i[1]  # 去之前定义好的url列表里找url应该执行的函数
            break
    if func:  # 如果能找到要执行的函数
        return func()  # 返回函数的执行结果
    else:
        return [bytes("404没有该页面", encoding="utf8"), ]


if __name__ == '__main__':
    httpd = make_server('', 8000, run_server)
    print("Serving HTTP on port 8000...")
    httpd.serve_forever()#发送给浏览器

html

<!DOCTYPE html>
<html lang="zh-CN">
<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>
    <h1>姓名:{{name}}</h1>#第一种写法
    <h1>爱好:</h1>
    <ul>
        {% for hobby in hobby_list %}#第二种写法循环键值对
        <li>{{hobby}}</li>
        {% endfor %}
    </ul>
</body>
</html>

reponse

wsgiref框架

1569213829577

http 规定请求和响应的标准

get获取数据 post 提交数据

1.客户端链接web服务器 connect

2.发送http请求

3.服务器接收请求并返回http响应

4.释放链接tcp连接

5.客户端浏览器解析html内容

http的分为两种

短链接和无连接 无状态
无连接发送完就断开链接,
无连接有两种模式
短链接
发送完数据等待几秒客户端的操作
无状态
不会保留状态

http

http协议
请求信息格式
GET / HTTP/1.1   请求行
Host: 127.0.0.1:8003  请求头
Connection: keep-alive
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36 
指定 浏览器格式
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
#空行br
请求数据  username=ziwen password=666


get请求 请求数据部分是没有数据的,get请求的数据在url上,在请求行里面,有大小限制,常见的get请求方式: 浏览器输入网址,a标签

post请求 请求数据在请求体(请求数据部分) ,数据没有大小限制, 常见方式:form表单提交数据
HTTP协议定义Web客户端如何从Web服务器请求Web页面,以及服务器如何把Web页面传送给客户端。HTTP协议采用了请求/响应模型。客户端向服务器发送一个请求报文,请求报文包含请求的方法、URL、协议版本、请求头部和请求数据。服务器以一个状态行作为响应,响应的内容包括协议的版本、成功或者错误代码、服务器信息、响应头部和响应数据.
以下是 HTTP 请求/响应的步骤:
1. 客户端连接到Web服务器
一个HTTP客户端,通常是浏览器,与Web服务器的HTTP端口(默认为80)建立一个TCP套接字连接。例如,http://www.luffycity.com。
2. 发送HTTP请求
通过TCP套接字,客户端向Web服务器发送一个文本的请求报文,一个请求报文由请求行、请求头部、空行和请求数据4部分组成。
3. 服务器接受请求并返回HTTP响应
Web服务器解析请求,定位请求资源。服务器将资源复本写到TCP套接字,由客户端读取。一个响应由状态行、响应头部、空行和响应数据4部分组成。
4. 释放连接TCP连接
若connection 模式为close,则服务器主动关闭TCP连接,客户端被动关闭连接,释放TCP连接;若connection 模式为keepalive,则该连接会保持一段时间,在该时间内可以继续接收请求;
5. 客户端浏览器解析HTML内容
客户端浏览器首先解析状态行,查看表明请求是否成功的状态代码。然后解析每一个响应头,响应头告知以下为若干字节的HTML文档和文档的字符集。客户端浏览器读取响应数据HTML,根据HTML的语法对其进行格式化,并在浏览器窗口中显示。
````````````````````````````````````
在浏览器地址栏键入URL,按下回车之后会经历以下流程:

1.浏览器向 DNS 服务器请求解析该 URL 中的域名所对应的 IP 地址;
2.解析出 IP 地址后,根据该 IP 地址和默认端口 80,和服务器建立TCP连接;
3.浏览器发出读取文件(URL 中域名后面部分对应的文件)的HTTP 请求,该请求报文作为 TCP 三次握手的第三个报文的数据发送给服务器;(根据不同路径返回不同数据)
4.服务器对浏览器请求作出响应,并把对应的 html 文本发送给浏览器;
5.释放 TCP连接;(conn.close())因为tcp是长连接 http协议的特点
6.浏览器将该 html 文本并显示内容;  

请求方法

八种动作

常用get post

#GET
//向指定的资源发出“显示”请求。使用GET方法应该只用在读取数据,而不应当被用于产生“副作用”的操作中,例如在Web Application中。其中一个原因是GET可能会被网络蜘蛛等随意访问。
#HEAD//
//与GET方法一样,都是向服务器发出指定资源的请求。只不过服务器将不传回资源的本文部分。它的好处在于,使用这个方法可以在不必传输全部内容的情况下,就可以获取其中“关于该资源的信息”(元信息或称元数据)。
#POST
//向指定资源提交数据,请求服务器进行处理(例如提交表单或者上传文件)。数据被包含在请求本文中。这个请求可能会创建新的资源或修改现有资源,或二者皆有。(把信息放入了请求数据)
PUT
//向指定资源位置上传其最新内容。
DELETE
//请求服务器删除Request-URI所标识的资源。
TRACE
//回显服务器收到的请求,主要用于测试或诊断。
OPTIONS
//这个方法可使服务器传回该资源所支持的所有HTTP请求方法。用'*'来代替资源名称,向Web服务器发送OPTIONS请求,可以测试服务器功能是否正常运作。
#CONNECT
//HTTP/1.1协议中预留给能够将连接改为管道方式的代理服务器。通常用于SSL加密服务器的链接(经由加密的HTTP代理服务器)。
patch
局部更新数据

img

http状态码

1xx消息——请求已被服务器接收,继续处理
2xx成功——请求已成功被服务器接收、理解、并接受
3xx重定向——需要后续操作才能完成这一请求
4xx请求错误——请求含有词法错误或者无法被执行
5xx服务器错误——服务器在处理某个正确请求时发生错误

重定向

例如一个http:jd.com/auth
1.输入 username和passwerd 提交数据
2.判断用户是否合法
3.如果是重定向 3xx
4.浏览器拿到网址,get请求获取对应的html
首页 http:www.jd.com

mvc和mtv框架

mvc
M --- models 数据库相关
v --- views 视图相关(逻辑)
C -- controller url控制器(url分发器,路由分发)
django-mtv
    M -- models 数据库相关
    T -- templates HTML相关 html就是模板
    V -- views  视图相关(逻辑)s
    + controller url控制器(url分发器,路由分发)

url

https默认 443端口

http默认 80端口

查询参数

?k1=v1&k2=v2

超文本传输协议(HTTP)的统一资源定位符将从因特网获取信息的五个基本元素包括在一个简单的地址中:
传送协议。
层级URL标记符号(为[////],固定不变)
访问资源需要的凭证信息(可省略) 
1.服务器。
    #//(通常为域名,有时为IP地址(dns解析))
2.端口号。
    //(以数字方式表示,若为HTTP的默认值“:80”可省略)
路径。
    //(以“/”字符区别路径中的每一个目录名称)
查询。
    //(GET模式的窗体参数,以“?”字符为起点,每个参数以“&”隔开,再以“=”分开参数名称与数据,通常以UTF8的URL编码,避开字符冲突的问题)
片段。(锚点)
    //以“#”字符为起点 
····································    
以http://www.luffycity.com:80/news/index.html?id=250&page=1 为例, 其中:
1.  http,是协议;
2.  www.luffycity.com,是服务器;
3.  80,是服务器上的网络端口号;
4.  /news/index.html,是路径;
5.  ?id=250&page=1,是查询。
大多数网页浏览器不要求用户输入网页中“http://”的部分,因为绝大多数网页内容是超文本传输协议文件。同样,“80”是超文本传输协议文件的常用端口号,因此一般也不必写明。一般来说用户只要键入统一资源定位符的一部分(www.luffycity.com:80/news/index.html?id=250&page=1)就可以了。

1569148055956

常见的请求头

user_agent:用什么浏览器访问的网站 发送的请求
content-type:application/json或application 
#指定请求体的格式 (服务端按照格式要求进行解析)

响应格式

url是127.0.0.1 /路径

响应可以不写头部字段 在回复信息的时候可以定制响应头

django请求生命周期

wsgi协议web服务网关接口
wsgi 是一种规范定义python的接口规范 可以搭配不同的应用程序
1.wsgiref本地做测试用,请求来了只能处理一个请求不能并发   
2.uwsgi linux和项目部署的时使用

浏览器向服务器请求数据(b/s架构)
本质是一个socket通信
1.浏览器请求发送到服务端 wsgi把接收到的请求 转发给django 
2.到达路由系统 进行路由匹配
3.到达视图进行业务处理 可以用orm从数据库中读取数据,调用模板进行渲染 渲染完成之后的字符串
4.通过wsgi 用send发送给客户端浏览器

请求(网址访问,提交数据等等) request
响应(回复页面,回复数据等等) response

下载安装django

pip3 install django==1.11.23

django创建项目

命令行

下载安装django

pip3 install django==1.11.23 
pip3 install django==1.11.23 http://mirrors.aliyun.com/pypi/simple/ 

创建项目
python36 manage.py runserver#开启django项目
python36 manage.py runserver 80 把端口号改成默认80
python36 manage.py runserver 0.0.0.0:80 其他人就可以访问了

创建app
python manage.py startapp app名称
指令船舰app需要的配置
项目的settings配置文件中,installapps的列表,添加一个app名称作为配置 
pycharm 创建完app之后,
如果在向创建新的app,需要指定创建app命令配置,
pycharm会自动配置app路径

djnago的py文件的分类

1.manage.py ----- Django项目里面的工具,通过它可以调用django shell和数据库,启动关闭项目与项目交互等,不管你将框架分了几个文件,必然有一个启动文件,其实他们本身就是一个文件。
2.settings.py ---- 包含了项目的默认设置,包括数据库信息,调试标志以及其他一些工作的变量。
3.urls.py ----- 负责把URL模式映射到应用程序w。
4.wsgi.py ---- runserver命令就使用wsgiref模块做简单的web server,后面会看到renserver命令,所有与socket相关的内容都在这个文件里面了,目前不需要关注它。

子项目的文件分类

views是写视图函数 视图类 代码逻辑

models是数据库的源 写与数据库相关的的

templatses 是模板 放置html xml等网络文件

wsgi用于书写socket

django基本操作

request对象 封装了所有请求  
request.method是当前请求方法 
````````````````````````````````````
.post 获取post请求的数据#请求体
.get 获取get请求的数据#问号以后的值
request.GET.get('pwd') 获取get 字典的值
request.POST.get('pwd')获取post 字典的值
post。get(“键”)取得的值是一个字符串
·······································

`````````````````````````````````````````````
注意'django.middleware.csrf.CsrfViewMiddleware',#安全机制

返回一个字典 获取值要把一个安全机制注释才能过

1569323222768

视图函数

视图函数
def articles(request,year,month): # 位置参数(形参) 2019 9
 print(year,type(year)) #2019 <class 'str'>  
#匹配出来的所有数据都是字符串
   print(month)
 return HttpResponse(year+'年'+ month +'月' +'所有文章')
 # 无名分组参数
    url(r'^articles/(\d+)/(\d+)/', views.articles), #articles/2019/9/

# 有名分组参数
url(r'^articles/(?P<xx>\d+)/(?P<oo>\d+)/', views.articles), #articles/2019/9/
#xx=2019  oo=9  关键字传参

def articles(request,oo,xx):  # 关键字传参 2019  9
    print(xx,type(xx)) #2019 <class 'str'>  #匹配出来的所有数据都是字符串
    print(oo)
    return HttpResponse(xx+'年'+ oo +'月' +'所有文章')

有名分组参数

# 有名分组参数
url(r'^articles/(?P<xx>\d+)/(?P<oo>\d+)/', views.articles), #articles/2019/9/
#xx=2019  oo=9  关键字传参

def articles(request,oo,xx):  # 关键字传参 2019  9
    print(xx,type(xx)) #2019 <class 'str'>  #匹配出来的所有数据都是字符串
    print(oo)
    return HttpResponse(xx+'年'+ oo +'月' +'所有文章')

无名分组参数

 # 无名分组参数
url(r'^articles/(\d+)/(\d+)/', views.articles), #articles/2019/9/
正则分组/(\d+)/(\d+)/会把匹配的  一一对应单独存储一个变量
(\d+)正则贪婪 满足一个或多个整数

具体示例

例如
html写法
<a href="/articles/2019/9">2019.9</a>#会把路径进行正则匹配 
#(要一一对应)
url(r"^articles/(\d+)/(\d+)/",views.articles),
#匹配的时候,返回对应的匹配的内容,
#articles是返回路径 后面匹配两个参数(正则匹配路径)

视图函数(request请求)补充

request是wsgirequest实例化的对象
1.print(request)打印出来的是--str--的返回值
requesrt这个对象含有————str————
#返回的都是字符串
2.print(request.path) #/home/  纯路径

3.print(request.path_info) #/home/  纯路径

4.print(request.get_full_path()) #/home/?a=1&b=2  全路径(不包含ip地址和端口)

5.print(request.body)  能够拿到请求数据部分的数据(post,get没有),get数据的内容在url里

6.print(request.META)
是一个Python字典,包含了所有本次HTTP请求的Header信息
查看需要在线json转换
user-agent返回

7.print(request.GET)返回get请求的数据类似字典的值
8.print(request.POST)返回get请求的数据类似字典的值
访问其他路径服务端会返回状态信息(状态码)

response响应的三个方法

三个方法都需要模块的引用
底部都有一个httpResponse 把字符串传入页面
form django.shortcuts import render,HttpResponse,redirect
1.HTTPResponse('字符串')#传入一个字符串 向浏览器返回一个页面
render 和redirect都是通过httpresponse传递给浏览器 

2.render(request,'xx.html')返回浏览器一个xx.html
#模板渲染 模板就是html页面 渲染就是字符串替换
'''
示例
'''
#home.html页面
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>24期官网</h1>
<h2>{{ namxx }}</h2>
</body>
</html>


#views视图.py (render有第三个参数是html传参使用)
def home(request):
    name = 'chao'
    return render(request, 'home.html',     {'namxx':name,})  #模板渲染(先把字符串替换了),这是在回复给浏览器之前做的事情
·······································

3.redirect 重定向

用法 redirect(路径) 示例:redirect('/index/')

会返回浏览器3xx一个重定向 返回一个redirect('/index/')路径

redirect示例
浏览器访问/index/#例如127.0.0.1/index/
urls.py
from django.conf.urls import url
from django.contrib import admin
from Django_test import views#引用 视图函数模块
urlpatterns = [
   url(r'^index/', views.index),
]
def home(request):
    print('xxxxx')
    return redirect('/index/') #重定向路径

1569402912947

FBV和CBV 视图(视图函数和视图类)

FBV是视图函数

def 函数名(request):
    函数体#进行判断
    return 要一个返回值返回给浏览器

CBV是视图类

urls写法

url(r'^login',views.LoginView.as_view())
1.加载到这一句的时候LoginView这个类直接调用执行类方法,LoginView没有as_view方法 去父类View去寻找这个方法
2.执行完之后返回一个view方法名
3.相当于视图函数#执行url(r'^login',views.view)
4.等待源码调用view方法(函数)

views视图类的写法

from django.views import View#引用View方法
 class LoginView(View):#创建一个类 继承父类view
    def get(self,request):##处理get请求直接定义get方法,不需要自己判断请求方法了,源码中用dispatch方法中使用了反射来处理的
        print('小小小小')
        return render(request,'login.html')
    def post(self,request)

view源码简化分析

执行步骤:
1.加载类名去调用执行as_view方法#views.loginview.as_view()#as_view
2.as_view返回一个view方法名
3.urls执行view方法
4.寻找到as_view函数里有view方法self = cls(**initkwargs)#实例化一个对象cls对应的就是 LoginView视图类
5. 继续往下执行return self.dispatch(request, *args, **kwargs)#这时self是LoginView视图类的实例化对象 去LoginView类中去寻找dispatch方法
6.LoginView视图类没有找到去对应的父类View去寻找
dispatch方法
7.找到http_method_names对应属性里面有各类方法
8.请求的方法名在这个属性中继续往下执行反射
9.利用反射去寻找对应的方法,如果找不到对应方法执行第三个参数报错
#注意
 getattr 第二个参数找不到就执行第三个参数 执行第三个方法直接报错返回 日志打印405


父类view
class View(object):

    http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace']
    @classonlymethod
    def as_view(cls, **initkwargs):
        for key in initkwargs:
            if key in cls.http_method_names:
                raise TypeError("You tried to pass in the %s method name as a "
                                "keyword argument to %s(). Don't do that."
                                % (key, cls.__name__))
            if not hasattr(cls, key):
                raise TypeError("%s() received an invalid keyword %r. as_view "
                                "only accepts arguments that are already "
                                "attributes of the class." % (cls.__name__, key))
      2.#as_view里面有一个view方法
        def view(request, *args, **kwargs):
            self = cls(**initkwargs)
            3.#实例化cls方法(就是LoginView视图类) 拿到自己类的对象
            if hasattr(self, 'get') and not hasattr(self, 'head'):
                self.head = self.get
            self.request = request
            self.args = args
            self.kwargs = kwargs
            return self.dispatch(request, *args, **kwargs)
        4.#执行到这发现 类调用一个方法 去视图类(LoginView)寻找dispatch方法,没有这个方法就去继承的父类去寻找 执行
        view.view_class = cls
        view.view_initkwargs = initkwargs

        update_wrapper(view, cls, updated=())

        update_wrapper(view, cls.dispatch, assigned=())
        return view 1.#返回一个view方法
    """
   dispatch方法
    """
5.找到dispatch方法执行
def dispatch(self, request, *args, **kwargs):
    #request.method.lower()取得请求对应的方法 方法名都是大写的所以需要小写对应
    #http_method_names去LoginView类去找,找不到去在源码中寻找(也就是继承的父类)
    if request.method.lower() in self.http_method_names:
        #请求的方法名在这个http_method_names属性中继续往下执行反射 
        #http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace']
        handler = getattr(self, request.method.lower(), self.http_method_not_allowed)
        #利用反射去寻找对应的方法
        #getattr 第二个参数找不到就执行第三个参数 执行第三个方法直接报错返回 日志打印405
    else:
        handler = self.http_method_not_allowed
    return handler(request, *args, **kwargs)
#为什么第三个参数返回405
handler = getattr(self, request.method.lower(), self.http_method_not_allowed)
getattr 第二个参数找不到就执行第三个参数
'''http_method_not_allowed方法'''#为什么第三个参数返回405

def http_method_not_allowed(self, request, *args, **kwargs):
    logger.warning(
        'Method Not Allowed (%s): %s', request.method, request.path,
        extra={'status_code': 405, 'request': request}
    )
    return http.HttpResponseNotAllowed(self._allowed_methods())

想法 在进行分发操作之前想要执行一些命令

自己重构父类的时候必须执行父类的分发操作

如果没有这个方法他会报错

(重构父类dispatch方法)

from django.views import View
class LoginView(View):
    def dispatch(self,request,*args,**kwargs):
        print("xxx请求来了")
    ret=super(LoginView,self).dispatch(request,*args,**)
   重构父类(view)的dispatch方法
 #def dispatch(self, request, *args, **kwargs):
  # if request.method.lower() in self.http_method_names:
    #handler = getattr(self,request.method.lower(),
    #self.http_method_not_allowed)
# else:
  #handler = self.http_method_not_allowed
  #return handler(request, *args, **kwargs)
#执行对应方法 获得返回值 

    print("执行结束")
    return ret
#相当于执行return handler(request, *args, **kwargs)
    def get(self,request):
        print('xxxx')
        return render(request,"login.html")
    def post(self,request):
        print(request.POST)
        return HttpResponse('登录成功')

图解

1569416028460

装饰器

有三种方式

在类上面必须指定请求方法

from django.utils.decorators import method_decorator
#必须引用django封装的装饰器
def wrapper(func):
    def inner(*args, **kwargs):
        print(11111)
        ret = func(*args, **kwargs)
        print(22222)

        return ret

    return inner

@method_decorator(wrapper,name='get')#第一种放松
class LoginView(View):
    def get(self,request):
        print('xxxx')
        return render(request,"login.html")

    @method_decorator(wrapper) #方式2
    def dispatch(self, request, *args, **kwargs):
        print('xx请求来啦!!!!')

        ret = super().dispatch(request, *args, **kwargs)

        print('请求处理的逻辑已经结束啦!!!')
        return ret

    @method_decorator(wrapper)#方式3
    def post(self,request):
         print(request.POST)
         return HttpResponse('登录成功')

模板渲染

猜你喜欢

转载自www.cnblogs.com/strawberry-1/p/11666564.html
今日推荐