1. 视图层views介绍
视图层是一个视图函数,简称视图,是一个简单的 Python 函数,它接受 Web 请求并且返回 Web 响应。
视图层中有两个重要的对象:请求对象(HttpRequest)与响应对象(HttpResponse)。
每个视图函数都负责返回也就是return 一个 HttpResponse 响应对象,HttpResponse 响应对象包括HttpResponse()、render()、redirect()三种形式。
响应可以是一个 HTML 页面、一个 404 错误页面、重定向页面、XML 文档、或者一张图片...
无论视图本身包含什么逻辑,都要返回响应。代码写在哪里都可以,只要在 Python 目录下面,一般放在项目的 views.py 文件中。
2. 请求对象: 又叫HttpRequest 对象,简称request对象
每个视图函数的第一个参数是一个 HttpRequest 对象
1. 属性
HttpRequest对象(request对象)包含如下属性:
属性 | 描述 |
path | 请求页面的全路径,不包括域名—例如, "/hello/"。 |
method | 请求中使用的HTTP方法的字符串表示。全大写表示。例如: if request.method == 'GET': |
GET | 包含所有HTTP GET参数的类字典对象。参见QueryDict 文档。 |
POST | 包含所有HTTP POST参数的类字典对象。参见QueryDict 文档。 服务器收到空的POST请求的情况也是有可能发生的。也就是说,表单form通过HTTP POST方法提交请求,但是表单中可以没有数据。因此,不能使用语句if request.POST来判断是否使用HTTP POST方法;应该使用if request.method == "POST" (参见本表的method属性)。 注意: POST不包括file-upload信息。参见FILES属性。 |
REQUEST | 为了方便,该属性是POST和GET属性的集合体,但是有特殊性,先查找POST属性,然后再查找GET属性。借鉴PHP's $_REQUEST。 例如,如果GET = {"name": "john"} 和POST = {"age": '34'},则 REQUEST["name"] 的值是"john", REQUEST["age"]的值是"34". 强烈建议使用GET and POST,因为这两个属性更加显式化,写出的代码也更易理解。 |
COOKIES | 包含所有cookies的标准Python字典对象。Keys和values都是字符串。 |
FILES | 包含所有上传文件的类字典对象。FILES中的每个Key都是<input type="file" name="" />标签中name属性的值. FILES中的每个value 同时也是一个标准Python字典对象,包含下面三个Keys:
注意:只有在请求方法是POST,并且请求页面中<form>有enctype="multipart/form-data"属性时FILES才拥有数据。否则,FILES 是一个空字典。 |
META | 包含所有可用HTTP头部信息的字典。 例如:
META 中这些头加上前缀 HTTP_ 为 Key, 冒号(:)后面的为 Value, 例如:
|
user | 是一个django.contrib.auth.models.User 对象,代表当前登录的用户。 如果访问用户当前没有登录,user将被初始化为django.contrib.auth.models.AnonymousUser的实例。 你可以通过user的is_authenticated()方法来辨别用户是否登录: if request.user.is_authenticated(): # Do something for logged-in users. else: # Do something for anonymous users. 只有激活Django中的AuthenticationMiddleware时该属性才可用 |
session | 唯一可读写的属性,代表当前会话的字典对象。只有激活Django中的session支持时该属性才可用。 |
raw_post_data | 原始HTTP POST数据,未解析过。 高级处理时会有用处。 |
2. 方法
Request对象也有一些有用的方法:
方法 | 描述 |
---|---|
__getitem__(key) | 返回GET/POST的键值,先取POST,后取GET。如果键不存在抛出 KeyError。 这是我们可以使用字典语法访问HttpRequest对象。 例如,request["foo"]等同于先request.POST["foo"] 然后 request.GET["foo"]的操作。 |
has_key() | 检查request.GET or request.POST中是否包含参数指定的Key。 |
get_full_path() | 返回包含查询字符串的请求路径。例如, "/music/bands/the_beatles/?print=true" |
is_secure() | 如果请求是安全的,返回True,就是说,发出的是HTTPS请求。 |
3. QueryDict对象(GET,POST)的方法
在HttpRequest对象中, GET和POST属性是django.http.QueryDict类的实例。
QueryDict类似字典的自定义类,用来处理单键对应多值的情况。
QueryDict实现所有python中已有的字典方法比如get(),items()等以及一些特有的方法,如下表:
方法 | 描述 |
---|---|
__getitem__ | 和标准字典的处理有一点不同,就是,如果Key对应多个Value,__getitem__()返回最后一个value。 |
__setitem__ | 设置参数指定key的value列表(一个Python list)。注意:它只能在一个mutable QueryDict 对象上被调用(就是通过copy()产生的一个QueryDict对象的拷贝). |
get() | 如果key对应多个value,get()返回最后一个value。 |
update() | 参数可以是QueryDict,也可以是标准字典。和标准字典的update方法不同,该方法添加字典 items,而不是替换它们: >>> q = QueryDict('a=1') >>> q = q.copy() # to make it mutable >>> q.update({'a': '2'}) >>> q.getlist('a') ['1', '2'] >>> q['a'] # returns the last ['2'] |
items() | 和标准字典的items()方法有一点不同,该方法使用单值逻辑的__getitem__(): >>> q = QueryDict('a=1&a=2&a=3') >>> q.items() [('a', '3')] |
values() | 和标准字典的values()方法有一点不同,该方法使用单值逻辑的__getitem__(): |
还有一些独有的方法:
方法 | 描述 |
---|---|
copy() | 返回对象的拷贝,内部实现是用Python标准库的copy.deepcopy()。该拷贝是mutable(可更改的) — 就是说,可以更改该拷贝的值。 |
getlist(key) | 返回和参数key对应的所有值,作为一个Python list返回。如果key不存在,则返回空list。 It's guaranteed to return a list of some sort.. |
setlist(key,list_) | 设置key的值为list_ (unlike __setitem__()). |
appendlist(key,item) | 添加item到和key关联的内部list. |
setlistdefault(key,list) | 和setdefault有一点不同,它接受list而不是单个value作为参数。 |
lists() | 和items()有一点不同, 它会返回key的所有值,作为一个list, 例如: >>> q = QueryDict('a=1&a=2&a=3') >>> q.lists() [('a', ['1', '2', '3'])] |
urlencode() | 返回一个以查询字符串格式进行格式化后的字符串(例如:"a=2&b=3&b=5")。 |
4. 常用属性
以下详细介绍几个常用的 request 属性。
1、GET
数据类型是 QueryDict,一个类似于字典的对象,包含 HTTP GET 的所有参数。
有相同的键,就把所有的值放到对应的列表里。
取值格式:对象.方法。
get():返回字符串,如果该键对应有多个值,取出该键的最后一个值。
代码举例:
新建一个newa.html
在urls.py中输入如下代码:
from django.urls import path
from . import views
urlpatterns = [
path('newa/', views.mydefC)
]
在views.py中
from django.http import HttpResponse
def mydefC(request):
name=request.GET.get("name")
return HttpResponse("姓名:{}".format(name))
在浏览器中输入如下:
?的意思是后面是参数,
浏览器反馈如下图,证明get对象ok
2、POST
数据类型是 QueryDict,一个类似于字典的对象,包含 HTTP POST 的所有参数。
常用于 form 表单,form 表单里的标签 name 属性对应参数的键,value 属性对应参数的值。
取值格式: 对象.方法。
get():返回字符串,如果该键对应有多个值,取出该键的最后一个值。
代码演示之前需要下载安装postman这个软件:
1. postman下载地址;Download Postman | Get Started for Free
点击下载安装
2. 下载安装后,注册,免费登录,new collection----->点击加号
3. 在urls.py中输入如下代码:
from django.urls import path
from . import views
urlpatterns = [
path('newa/', views.mydefC)
]
4. 在views.py中 ,使用POST方法,代码如下:
from django.http import HttpResponse
def mydefC(request):
name=request.POST.get("name")
return HttpResponse("姓名:{}".format(name))
5. 然后在POSTMAN中,选色POST,URL输入地址,选择body,forms-data, key下面输入name,Value下面输入张三, 然后send
可见下面出现:姓名:张三
而真正的网页显示如下:
6. 其间出现如下 CSRF verification failed. Request aborted. 报错,
解决办法:
.在setting.py 里注释掉 # ‘django.middleware.csrf.CsrfViewMiddleware’
3、body
数据类型是二进制字节流,是原生请求体里的参数内容,在 HTTP 中用于 POST,因为 GET 没有请求体。
在 HTTP 中不常用,而在处理非 HTTP 形式的报文时非常有用,例如:二进制图片、XML、Json 等。
1. 在views.py中 ,使用body方法,代码如下:
from django.http import HttpResponse
def mydefC(request):
name=request.body
print(name)
return HttpResponse("姓名")
2. 然后在postman里面重复步骤和POST 方法内的步骤,其实也不需要重新输入,直接点击send,
反馈的只是httpresponse里面的内容“姓名”, 因为reques.body无法显示,所以只能用print函数,
在cmd窗口中可以看到print函数打印出来的结果,是一串二进制字节流。
4、path
获取 URL 中的路径部分,数据类型是字符串。
1. 在views.py中 ,使用body方法,代码如下:
改成name= request.path
from django.http import HttpResponse
def mydefC(request):
name=request.path
print(name)
return HttpResponse("姓名")
2. 然后在postman里面重复步骤和POST 方法内的步骤,其实也不需要重新输入,直接点击send,内容和上面的body方法完全一样
3. 但是在cmd中可以看到打印的name,就是path
5、method
获取当前请求的方式,数据类型是字符串,且结果为大写。
1. 在views.py中 ,使用body方法,代码如下:
改成name= request.method ,其他不变
from django.http import HttpResponse
def mydefC(request):
name=request.method
print(name)
return HttpResponse("姓名")
2. 然后在postman里面重复步骤和POST 方法内的步骤,其实也不需要重新输入,直接点击send,内容和上面的body方法完全一样
3. 但是在cmd中可以看到打印的我们用的请求的方法POST,如果我们用get方法,就会显示get方法
3. 响应对象:HttpResponse 对象
响应对象主要有三种形式:HttpResponse()、render()、redirect()。
HttpResponse(): 返回文本,参数为字符串,字符串中写文本内容。如果参数为字符串里含有 html 标签,也可以渲染。
render(): 返回文本,第一个参数为 request,第二个参数为字符串(页面名称),第三个参数为字典(可选参数,向页面传递的参数:键为页面参数名,值为views参数名)。
redirect():重定向,跳转新页面。参数为字符串,字符串中填写页面路径。一般用于 form 表单提交后,跳转到新页面。
1. HttpResponse()
1. 在views.py中 ,使用HttpResponse(), 代码如下:
from django.http import HttpResponse
def mydefC(request):
return HttpResponse("我爱中国")
2. 在路由newa中映射到views.mydefC,就能显示如下:
3. 如果将 HttpResponse()里面的内容改成一串代码,也可以执行:
from django.http import HttpResponse
def mydefC(request):
return HttpResponse("<a href='https://blog.csdn.net/weixin_42888180?spm=1000.2115.3001.5343'>我的主页</a>")
4. 网页显示:超链接
2. render()
1. 在views.py中 ,使用render(), 代码如下:
注意:此时import 的是render
from django.shortcuts import render #注意这行代码有变化
def mydefC(request):
name="张三"
return render(request,"newa.html",{"abc":name})
2. 在newa.html 中输入: <ul>{{abc}}</ul>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<ul>{{abc}}</ul>
</body>
</html>
2. 网页显示 ,成功!render中响应了一个网页,因此会打开这个网页,并且该网页里面有一个参数叫abc,并传入了一个这个参数的值name
2. redirect()
1. 在views.py中 ,使用redirect(), 代码如下:
注意:此时import 的是redirect
from django.shortcuts import redirect
def mydefC(request):
return redirect("/base/")
2. 在地址栏输入: http://127.0.0.1:8002/newa/ 结果显示:报错了 !没有redirect成功?
3. 此时,需要在 urls.py中输入2个路由
urlpatterns = [
path('newa/', views.mydefC),
path('base/', views.mydefB),
]
同时, 在views.py中定义mydefB,
def mydefC(request):
return redirect("/base/")
def mydefB(request):
return render(request,"base.html")
之前定义的base.html代码如下:不用改变
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>DOTmanager教程</title>
</head>
<body>
<h1>hello world!</h1>
<p>Django 测试</p>
{%block body%}
<p>original</p>
{%endblock%}
</body>
</html>
4.最终在地址栏输入newa.html的地址会自动跳转到base.html
实际上: render 和 redirect 是在 HttpResponse 的基础上进行了封装:
-
- render:底层返回的也是 HttpResponse 对象
- redirect:底层继承的是 HttpResponse 对象