3.Django视图函数
一、django的视图函数views
一个视图函数(类),简称视图,是一个简单的Python 函数(类),它接受Web请求并且返回Web响应。
响应可以是一张网页的HTML内容,一个重定向,一个404错误,一个XML文档,或者一张图片。
视图层,熟练掌握两个对象即可:请求对象(request)和响应对象(HttpResponse)
二、request对象
当一个页面被请求时,Django就会创建一个包含本次请求原信息(请求报文中的请求行、首部信息、内容主体等)的HttpRequest对象。Django会将这个对象自动传递给响应的视图函数,一般使用request 参数表示这个对象。
1、request常用属性
- method 一个字符串,表示请求中使用的HTTP方法。
- path_info 在某些Web服务器配置下,主机名之后的URL部分分为脚本前缀部分和路径信息部分。
path_info
无论使用什么Web服务器,该属性始终包含路径的路径信息部分。使用它代替,path
可以使您的代码更容易在测试服务器和部署服务器之间移动。 - GET 包含所有HTTP GET参数的类字典对象
- POST 包含所有HTTP POST参数的类字典对象
- body post请求提交的最原始的数据,原始的HTTP请求主体为字节字符串。这对于以不同于常规HTML格式的方式处理数据很有用:二进制图像,XML有效负载等。
- META 包含所有可用HTTP标头的字典。可用的标头取决于客户端和服务器,但以下是一些示例:
CONTENT_LENGTH
–请求正文的长度(以字符串形式)。CONTENT_TYPE
–请求正文的MIME类型。HTTP_ACCEPT
–响应可接受的内容类型。HTTP_ACCEPT_ENCODING
–响应的可接受编码。HTTP_ACCEPT_LANGUAGE
–可接受的响应语言。HTTP_HOST
–客户端发送的HTTP Host标头。HTTP_REFERER
–推荐页面(如果有)。HTTP_USER_AGENT
–客户端的用户代理字符串。QUERY_STRING
–查询字符串,作为单个(未分析)字符串。REMOTE_ADDR
–客户端的IP地址。REMOTE_HOST
–客户端的主机名。REMOTE_USER
–由Web服务器验证的用户(如果有)。REQUEST_METHOD
–诸如"GET"
或的字符串"POST"
。SERVER_NAME
–服务器的主机名。SERVER_PORT
–服务器的端口(以字符串形式)
2、request常用方法
1、get_host()
根据从HTTP_X_FORWARDED_HOST(如果打开 USE_X_FORWARDED_HOST,默认为False)和 HTTP_HOST 头部信息返回请求的原始主机。
如果这两个头部没有提供相应的值,则使用SERVER_NAME 和SERVER_PORT,在PEP 3333 中有详细描述。
USE_X_FORWARDED_HOST:一个布尔值,用于指定是否优先使用 X-Forwarded-Host 首部,仅在代理设置了该首部的情况下,才可以被使用。
例如:"127.0.0.1:8000"
注意:当主机位于多个代理后面时,get_host() 方法将会失败。除非使用中间件重写代理的首部。
2、get_full_path()
返回 path,如果可以将加上查询字符串。
例如:"/index/?username=an&password=123"
3、get_signed_cookie(key, default=RAISE_ERROR, salt='', max_age=None)
返回签名过的Cookie 对应的值,如果签名不再合法则返回django.core.signing.BadSignature。
如果提供 default 参数,将不会引发异常并返回 default 的值。
可选参数salt 可以用来对安全密钥强力攻击提供额外的保护。max_age 参数用于检查Cookie 对应的时间戳以确保Cookie 的时间不会超过max_age 秒。
4、HttpRequest.is_secure()
如果请求时是安全的,则返回True;即请求通是过 HTTPS 发起的。
5、is_ajax()
如果请求是通过XMLHttpRequest 发起的,则返回True,方法是检查 HTTP_X_REQUESTED_WITH 相应的首部是否是字符串'XMLHttpRequest'。
大部分现代的 JavaScript 库都会发送这个头部。如果你编写自己的 XMLHttpRequest 调用(在浏览器端),你必须手工设置这个值来让 is_ajax() 可以工作。
如果一个响应需要根据请求是否是通过AJAX 发起的,并且你正在使用某种形式的缓存例如Django 的 cache middleware,
你应该使用 vary_on_headers('HTTP_X_REQUESTED_WITH') 装饰你的视图以让响应能够正确地缓存。
三、response对象
与由Django自动创建的HttpRequest对象相比,HttpResponse对象是我们的职责范围了。我们写的每个视图都需要实例化,填充和返回一个HttpResponse。HttpResponse类位于django.http模块中。
相关方法
HtppResponse() --回复字符串的
render() -- 回复一个html页面
redirect() --重定向
HttpResponse.content:响应内容
HttpResponse.charset:响应内容的编码
HttpResponse.status_code:响应的状态码
重定向的状态码:
1)301和302的区别
301和302状态码都表示重定向,就是说浏览器在拿到服务器返回的这个状态码后会自动跳转到一个新的URL地址,这个地址可以从响应的Location首部中获取
(用户看到的效果就是他输入的地址A瞬间变成了另一个地址B)——这是它们的共同点。
他们的不同在于。301表示旧地址A的资源已经被永久地移除了(这个资源不可访问了),搜索引擎在抓取新内容的同时也将旧的网址交换为重定向之后的网址;
302表示旧地址A的资源还在(仍然可以访问),这个重定向只是临时地从旧地址A跳转到地址B,搜索引擎会抓取新的内容而保存旧的网址。 SEO302好于301
2)重定向原因:
(1)网站调整(如改变网页目录结构);
(2)网页被移到一个新地址;
(3)网页扩展名改变(如应用需要把.php改成.Html或.shtml)。
这种情况下,如果不做重定向,则用户收藏夹或搜索引擎数据库中旧地址只能让访问客户得到一个404页面错误信息,访问流量白白丧失;再者某些注册了多个域名的
网站,也需要通过重定向让访问这些域名的用户自动跳转到主站点等。
四、CBV和FBV
FBV(function base views) 就是在视图里使用函数处理请求。之前都是FBV模式写的代码。
CBV(class base views) 就是在视图里使用类处理请求。
Python是一个面向对象的编程语言,如果只用函数来开发,有很多面向对象的优点就错失了(继承、封装、多态)。所以Django在后来加入了Class-Based-View。可以让我们用类写View。这样做的优点主要下面两种:
- 提高了代码的复用性,可以使用面向对象的技术,比如Mixin(多继承)
- 可以用不同的函数针对不同的HTTP方法处理,而不是通过很多if判断,提高代码可读性
写一个处理GET方法的view,用函数写
from django.http import HttpResponse
def my_view(request):
if request.method == 'GET':
return HttpResponse('OK')
用class-based view写
from django.http import HttpResponse
from django.views import View
class MyView(View):
def get(self, request):
return HttpResponse('OK')
Django的url是将一个请求分配给可调用的函数的,而不是一个class。针对这个问题,class-based view提供了一个as_view()
静态方法(也就是类方法),调用这个方法,会创建一个类的实例,然后通过实例调用dispatch()
方法,dispatch()
方法会根据request的method的不同调用相应的方法来处理request(如get()
, post()
等)。到这里,这些方法和function-based view差不多了,要接收request,得到一个response返回。如果方法没有定义,会抛出HttpResponseNotAllowed异常。
使用CBV时,urls.py中也做对应的修改
# urls.py
from django.conf.urls import url
from myapp.views import MyView #引入我们在views.py里面创建的类
urlpatterns = [
url(r'^index/$', MyView.as_view()),
]
CBV通过不同的请求方法找到对应的视图类中的方法
五、视图加装饰器
装饰器使用要点
- 添加装饰器前必须导入from django.utils.decorators import method_decorator
- 添加装饰器的格式必须为@method_decorator(),括号里面为装饰器的函数名
- 给类添加是必须声明name
1、给FBV添加装饰器
FBV本身就是一个函数,所以和给普通的函数加装饰器无差:
2、给CBV添加装饰器
类中的方法与独立函数不完全相同,因此不能直接将函数装饰器应用于类中的方法 ,我们需要先将其转换为方法装饰器。
Django中提供了method_decorator装饰器用于将函数装饰器转换为方法装饰器。
为类方法添加装饰器,需要导入method_decorator
from django.utils.decorators import method_decorator
class LoginView(View):
@method_decorator(f) # f为上面写的装饰器
def get(self, request):
print('执行了get方法')
return render(request, 'login2.html')
扩展:使用父类的dispatch方法,类似于每个类方法都有的隐藏装饰器
# CBV
class LoginView(View):
def dispatch(self, request, *args, **kwargs):
print('请求来了')
ret = super().dispatch(request, *args, **kwargs)
print('到点了,该走了')
return ret
# GET
def get(self, request):
print('执行了get方法')
return render(request, 'login2.html')
def post(self, request):
print('执行了post方法')
username = request.POST.get('username')
password = request.POST.get('password')
print(username, password)
return HttpResponse('登陆成功')