《 Django 框架》课程第 1 次教学 – 视图高级
一、内置错误视图
1 、视图
一个视图函数,简称视图,是一个简单的Python函数,它接受Web请求并且返回Web响应。代码写在哪里也无所
谓,只要它在你的应用目录下面。但是为了方便视图一般被定义在”应用/views.py”文件中。
视图的第一个参数必须为HttpRequest实例,还可能包含下参数如:
通过正则表达式组获得参数
视图必须返回一个HttpResponse对象或子对象作为响应。
2 、错误视图
Django内置处理HTTP错误的视图,主要错误及视图包括
404 错误:pagenotfound视图
500 错误:server error视图
400 错误:bad request视图
403 错误:permission_denied视图
如果想要看到错误视图,而不是错误调试信息的需要设置setting.py配置文件的调试开关设置为False:
ALLOWED_HOSTS允许所有主机访问。
DEBUG = False ALLOWED_HOSTS = ["*",]
404 错误及视图
将请求地址进行url匹配后,没有找到匹配的正则表达式,则调用 404 视图,这个视图会调用 404 .html的模板
进行渲染
404 视图默认情况下定义在'django.views.defaults.page_not_found'
django自带 404 模板
视图传递变量request_path给模板,是导致错误的URL
自定义错误模板:在项目的templates目录下创建一个名字叫 404 .html的模板文件:当发生 404 错误时, 404
视图会调用templates中的模板文件而不再调用自带的模板。
其他错误处理方式相同。
3 、自定义错误视图
Django中默认的错误视图对于大多数web应用已经足够了,但是如果你需要任何自定义行为,只要在你的URLconf
中指定下面的处理器(在其他任何地方设置它们不会有效)。
在应用下的urls.py中自定义错误视图。 handler 404 覆盖了page_not_found()视图:
404 自定义错误视图
def my_page_not_found_view(request):
'''404错误视图'''
return HttpResponse('请求不存在')
访问错误url
其他错误视图跟 404 错误一样。 handler 500 覆盖了server_error()视图:
handler 500 ='mysite.views.my_custom_error_view'
handler 403 覆盖了permission_denied()视图:
handler403 = 'mysite.views.my_custom_permission_denied_view'
handler 400 覆盖了bad_request()视图:
handler400 = 'mysite.views.my_custom_bad_request_view'
4 、模型类 get 方法错误处理
在讲模型的get方法的时候讲到过,使用get方法如果数据不存在会抛出一个DoesNotExist的异常.比如用户访问
博客的详细页请求传过来一个id据库中不存在,那么用户就会看到报错页面。
get_object_or_ 404 的介绍: 我们原来调用django 的get方法,如果查询的对象不存在的话,会抛出一个
DoesNotExist的异常。现在我们调用djangoget_object_or_ 404 方法,它会默认的调用django的get方法,如果
查询的对象不存在的话,会抛出一个Http 404 的异常,返回 404 错误页面。这样用户就不会觉得是服务器异常。而
是自己访问的路径不对。
from django.shortcuts import get_object_or_404
def detail(request, id):
# post = Post.post_object.get(pk=id)
post = get_object_or_404(Post,pk=id) # 调用get_object_or_404方法,如果没有错误返回结果
return render(request, 'personal_blog/detail.html', context={"post": post})
get_object_or_ 404 第一个参数是需要查询的模型类, 第二个参数是 查询条件。
二、HttpRequest 对象
1 、 HttpRequest
服务器接收到http协议的请求后,Django会建立一个包含请求元数据的HttpRequest对象,这个对象不需要
我们创建,直接使用服务器构造好的对象使用就可以
2 、属性
scheme: 一个字符串,表示请求的方案(通常是http 或https)。
body: 一个字节字符串,表示原始HTTP 请求的正文。
path: 一个字符串,表示请求的页面的完整路径,不包含域名
method:一个字符串,表示请求使用的HTTP 方法。常用值包括:'GET'、'POST'
encoding:一个字符串,表示提交的数据的编码方式(如果为None 则表示使用DEFAULT_CHARSET 设置,一般 为utf-8)。这个属性是可写的,你可以修改它来修改访问表单数据使用的编码。接下来对属性的任何访问(例如从 GET 或 POST 中读取数据)将使用新的encoding 值
GET: 一个类似于字典的对象,包含HTTP GET 的所有参数 POST: 一个包含所有给定的HTTP POST参数的类字典对象,提供了包含表单数据的请求。
COOKIES:一个标准的Python 字典,包含所有的cookie。键和值都为字符串。
FILES: 一个类似于字典的对象,包含所有的上传文件。FILES 中的每个键为 中的name。 session:一个既可读又可写的类似于字典的对象,表示当前的会话。只有当Django 启用会话的支持时才可用。
META:一个标准的Python 字典,包含所有的HTTP 头部。
CONTENT_LENGTH —— 请求的正文的长度(是一个字符串)。
CONTENT_TYPE —— 请求的正文的MIME 类型。
HTTP_ACCEPT —— 响应可接收的Content-Type。
HTTP_ACCEPT_ENCODING —— 响应可接收的编码。
HTTP_ACCEPT_LANGUAGE —— 响应可接收的语言。
HTTP_HOST —— 客服端发送的HTTP Host 头部。 HTTP_REFERER —— Referring 页面。
HTTP_USER_AGENT —— 客户端的user-agent 字符串。
QUERY_STRING —— 单个字符串形式的查询字符串(未解析过的形式)。
REMOTE_ADDR —— 客户端的IP 地址。 REMOTE_HOST —— 客户端的主机名。 REMOTE_USER —— 服务器认证后的用户。
REQUEST_METHOD —— 一个字符串,例如"GET" 或"POST"。
SERVER_NAME —— 服务器的主机名。 SERVER_PORT —— 服务器的端口(是一个字符串)。
在浏览器中开发者工具->网络 中可以看到请求信息:
示例:scheme,path,encoding:
def info(request):
HttpRequest对象属性
str = '请求的方案:%s<br>路径:%s<br>编码%s'(request.scheme,request.path,request.encoding)
return HttpResponse(str)
method 表示请求使用的HTTP方式创建三个视图:
def method1(request):
return render(request,'personal_blog/method1.html')
def method2(request):
return HttpResponse(request.method) # 返回请求方式
def method3(request):
return HttpResponse(request.method) # 返回请求方式
配置URL:
url(r'^method1/$', views.method1),
url(r'^method2/$', views.method2),
url(r'^method3/$', views.method3),
创建模板:method1.html 写入下面内容:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body> <a href="/blog/method2/">方式一:get</a>
<br>
<br> <form method="post" action="/blog/method3/">
<input type="submit" value="方式二:post">
</form>
</body>
</html>
浏览其中访问:http://127.0.0.1:8000/blog/method1/ 点击链接 方式一:get,转到method2,浏览器接收到请求方式’GET’
点击链接 方式二:post, 转到method3,会出现拒绝访问。django默认开启 csrf 跨站请求伪造,后面会详细讲, 这里先将csrf关闭。
将项目目录的settings.py文件,将MIDDLEWARE_CLASSES项的csrf注释
MIDDLEWARE_CLASSES=(
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
#'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'django.middleware.security.SecurityMiddleware',
)
注释之后重新访问:
META 一个标准的Python 字典,包含所有的HTTP头部。
defmetainfo(request):
m=request.META
str=''
将http请求头拼接返回给浏览器,查看http请求头信息
forkey,valueinm.items():
str+='%s:%s'%(key,value)+'<br>'return
HttpResponse(str)
配置ur
url(r'^metainfo/$',views.metainfo),
在浏览器访问; http://127.0.0.1:8000/blog/metainfo/
; 3 、 QueryDict 对象
在HttpRequest 对象中,GET 和POST 属性是django.http.QueryDict 的实例,它是一个自定义的类似字典的
类,用来处理同一个键带有多个值。与python字典不同,QueryDict类型的对象用来处理同一个键带有多个值
的情况
方法:get:根据键获取值,如果一个键同时拥有多个值将获取最后一个值,如果键不存在则返回None值,可以设置
默认值进行后续处理
getlist:根据键获取值,值以列表返回,可以获取指定键的所有值如果键不存在则返回空列表[],可以设置默认值
进行后续处理
这两个方法用于获取url? 号后面的参数
get():
dict=request.GET
dict.get('键','默认值') # 如果GET参数里没有这个键,那么将使用默认值。默认值是一个可选参数
getlist():
dict=request.GET
dict.getlist('键','默认值') # 获取一键多值的情况,返回指定键的所有值的列表
4 、 GET 属性
请求参数:在请求地址结尾使用?,之后以”键=值”的格式拼接,多个键值对之间以&连接例如:
https://www.baidu.com/s?ie=UTF-8&wd=pythonie=UTF-8&wd=python ?之后的就是请求参数
请求参数键ie,wd值分别为UTF- 8 ,python
在Django中可以使用HttpRequest对象的GET属性获得get方式请求的参数,如果是post请求则用POST属性获取请求
参数。
键是开发人员在编写代码时指定的,值可能是用户输入,或者动态生成。
示例:
在创建一个模板get.html,编辑两个a标签
personal_blog/get.html
<!DOCTYPEhtml>
<htmllang="en">
<head>
<metacharset="utf- 8 ">
<title>Title</title>
</metacharset="utf-></head>
<body>
</body></htmllang="en">
<ahref=" 1 blog get ?a="1" &b="2" ">get:一键一值
<ahref=" 2 blog get ?a="1" &b="2" &a="3" ">get 2 :一键多值
</ahref="></ahref=">
https://www.baidu.com/s?ie=UTF-8&wd=pythonie=UTF-8&wd=python ?之后的就是请求参数
defget(request):
return render(request,'personal_blog/get.html')
defget 1 (request):
dict=request.GET#获取get请求的参数,返回一个QueryDict对像a
=dict.get('a') #get方法获取值
b=dict.get('b')
c=dict.get('c','我是默认值c')#不存在键c,使用默认值
returnHttpResponse('a:%s,b:%s,c:%s'%(a,b,c))
defget 2 (request):
dict=request.GET#获取get请求的参数,返回一个QueryDict对像
a=dict.getlist('a') #getlist方法获取一键多值的参数,返回列表
b=dict.get('b')
returnHttpResponse('a:%s,b:%s'%(a,b))
配置url
url(r'^get/$', views.get),
url(r'^get1/$', views.get1),
url(r'^get2/$', views.get2),
访问: http://127.0.0.1:8000/blog/get/
点击get:一键一值, 视图接收到请求参数 a,bc不存在则使用默认值。
点击get 2 :一键多值 视图接收到请求参数 a为多值,getlist返回包含所有值得列表。
; 5 、 POST 属性
在进行form表单提交的时候将method方式改成post方式,提交表单时会发起POST请求。需要使用HttpRequest
对象的POST属性接收参数,POST属性返回QueryDict类型的对象
在表单进行提交时,控件name属性的值作为键,value属性的值为值,构成键值对提交,如果控件没有name属性
那么将不进行提交。
radio控件,name属性的值相同为一组单选,将选中的提交checkbox控件,name属性的值相同为一组,被
选中的项都会被提交,出现一键多值的情况
创建一个form表单的模板 personal_blog/post.html
<metacharset="utf- 8 ">
<title>表单</title>
<body>
<formmethod="post"action=" 1 blog post ">
姓名:<inputtype="text"name="uname">
密码:<inputtype="password"name="upwd">
性别:<inputtype="radio"name="ugender"value=" 1 ">男
<inputtype="radio"name="ugender"value=" 0 ">女
爱好:<inputtype="checkbox"name="uhobby"value="抽烟">抽烟
<inputtype="checkbox"name="uhobby"value="喝酒">喝酒
<inputtype="checkbox"name="uhobby"value="烫头">烫头
<inputtype="submit"value="提交">
</inputtype="submit"value="提交"></inputtype="checkbox"name="uhobby"value="烫头"></inputtype="checkbox"name="uhobby"value="喝酒"></inputtype="checkbox"name="uhobby"value="抽烟"></inputtype="radio"name="ugender"value="></inputtype="radio"name="ugender"value="></inputtype="password"name="upwd"></inputtype="text"name="uname"></formmethod="post"action="></body></metacharset="utf->
创建视图返回模板form.html
defpost(request):
return render(request,'personal_blog/form.html')
创建模板展示用户form表单输入的数据:
<!DOCTYPEhtml>
<htmllang="en">
<head>
<metacharset="utf- 8 ">
<title>Title</title>
</metacharset="utf-></head>
<body>
姓名:{{uname}}
密码:{{upwd}}
性别:{{ugender}}
爱好:
{%forloveinuhobby%}
{{love}}
{%endfor%}
</body>
</htmllang="en">
创建视图接收post请求参数调用 post 1 .html模板,将post请求的参数传给模板渲染
defpost 1 (request):
p_dict=request.POST #获取post请求参数
uname=p_dict.get('uname')
upwd=p_dict.get('upwd')
ugender=
p_dict.get('ugender')
uhobby=p_dict.getlist('uhobby')#爱好是一键多值,使用getlist方法获取所有爱好
context={'uname':uname,'upwd':upwd,'ugender':ugender,'uhobby':uhobby}
配置url
url(r'^post/$',
views.post),
url(r'^post 1 /$',
三、HttpResponse对象
与由Django自动创建的HttpRequest对象相比,HttpResponse对象由程序员创建.创建的每个视图负责初始化实
例,填充并返回一个 HttpResponse或者子对象.
HttpResponse 类是在django.http模块中定义的。
1 、 HttpResponse 属性
content:表示返回的内容
charset:表示response采用的编码字符集,默认为utf- 8
status_code:返回的HTTP响应状态码
content-type:指定返回数据的的MIME类型,默认为'text/html'
修改响应状态码:
defresp(request):
response=
HttpResponse(content='hhh',status= 300 ,)
print(response.status_code)
returnresponse
配置url
url(r'^resp/$',views.resp),
2 、 HttpResponse 方法
set_cookie:设置
Cookie信息write:
向响应体中写数据
Cookie最早是网景公司的前雇员Lou Montulli在 1993 年 3 月的发明。
Cookie是由服务器端生成,发送给一般是浏览器,浏览器会将Cookie的key/value保存到某个目录下的文本文件内,
下次请求同一网站时就发送该Cookie给服务器(前提是浏览器设置为启用cookie)。
Cookie名称和值可以由服务器端开发自己定义,这样服务器可以知道该用户是否合法用户以及是否需要重新登录
等。
Cookie基于域名安全,不同域名的Cookie是不能互相
问的,浏览器每次请求时都会将cookie发给服务器
典型应用:网站的广告推送,购物车,记住用户名
cookie是网站以键值对格式存储在浏览器中的一段纯文本信息。
set_cookie(key,value='',max_age=None,expires=None,path='/',domain=None,secure=None,httponly=False)
max_age 以秒为单位,如果Cookie 只应该持续客户端浏览器的会话时长则应该为None(默认值)。
expires应该是一个UTC”Wdy,DD-Mon-YYHH:MM:SSGMT”格式的字符串,或者一个datetime.datetime对象。如果
expires 是一个datetime 对象,则max_age会通过计算得到。
max_age与expires二选一
如果不指定过期时间,则关闭浏览器过期
如果你想设置一个跨域的Cookie,请使用domain 参数。例如,domain=”.lawrence.com” 将设置一个
http://www.lawrence.co
m、blogs.lawrence.com 和calendars.lawrence.com 都可读的Cookie。否则,Cookie 将只能被设置它
的域读取。
如果你想阻止客服端的JavaScript 访问Cookie,可以设置httponly=True。
delete_cookie(key):删除指定的key的Cookie,如果key不存在则什么也不发生
创建视图设置cookie
def
set_cookie(request)
:
response=HttpResponse("设置
cookie")
response.set_cookie('username',
'admin')
response.set_cookie('password',' 123456 ',max_age= 60 * 60 * 12 )#设置超时时间 60 * 60 * 12 秒
创建视图删除cookie
defdelete_cookie(request):
response=HttpResponse('删除cookie')
response.delete_cookie('password')#删除键为password的
cookiereturnresponse
创建视图获取cookie
def
get_cookie(request):
cookie=request.COOKIES#获取
cookieusername=
cookie.get('username')password=
cookie.get('password')
response=HttpResponse('%s%s'%(username,password))# 将获取到的cookie返回
returnresponse
配置url
url(r'^set_cookie/$',views.set_cookie),
url(r'^delete_cookie/$',views.delete_cookie),
url(r'^get_cookie/$', views.get_cookie),
在浏览器中查看cookie以火狐为例子:在浏览器中按F 12 ,或者在设置找到开发者管理工具,由于没有写入
cookie所有cookie列表为空
访问: http://127. 0. 0. 1 : 8000 /blog/set_cookie/ 设置cookie
访问:http:// 127. 0. 0. 1 : 8000 /blog/get_cookie/
; 4 、子类 JsonResponse
在web开发中,前端会经常要求后台传输数据时返回json格式的数据。JSON(JavaScriptObjectNotation,JS对
象标记)是一种轻量级的数据交换格式。json数据是类似字典的格式,键/值对使用””。比如:
{“username”:”admin”,”password”:” 123456 “}
django 使用JsonResponse对象返回json数据
JsonResponse继承自HttpResponse对象,被定义在django.http模块中 接收字典作为参数
fromdjango.httpimportJsonResponse
defjson(request):
return JsonResponse({'username':'admin'})
配置url
url(r'^json/$',views.json),
访问视图:http:// 127. 0. 0. 1 : 8000 /blog/json/ ,可以看到返回的是json数据
所以在以后web开发中,如果前端页面需要json格式的数据,需要先将数据构造成python字典对象,然后使用
JsonRespouse返回。
5 、子类 HttpResponseRedirect 重定向对象
当一个视图处理完成后,不需要向客户端呈现数据,而是跳转到其他页面,比如用户登录成功之后,需要跳转到登录
成功后的页面。此时就需要模拟一个用户请求的效果,从一个视图转到另外一个视图,就称为重定向。
django中提供HttpResponseRedirect 对象实现重定向功能。HttpResponseRedirect定义在
django.http模块中要使用HttpResponseRedirect 需要先导入
fromdjango.httpimportHttpResponseRedirect
下面我们用模拟登录做示例:定义一个登录页面模板。当登录成功之后跳转到博客首页。如果账号密码校验错
误,返回原来的登录页面。登录模板login.html
<!DOCTYPEhtml>
<htmllang="en">
<head>
<metacharset="utf- 8 ">
<title>Title</title>
</metacharset="utf-></head>
<body>
<formmethod="post"action=" blog login ">
用户名:<inputname="uname"value="{{uname}}">
密码:<inputname="upwd"value="{{upwd}}">
<inputtype="submit"value="登录">
</inputtype="submit"value="登录"></inputname="upwd"value="{{upwd}}"></inputname="uname"value="{{uname}}"></formmethod="post"action="></body></htmllang="en">
<spanstyle="color:red">{{iserror}}
</spanstyle="color:red">
处理用户登录视图:
def
login(request)
:
#帐号密码
username='老
狗'password=
' 123456 '
ifrequest.method=='GET':
returnrender(request,
'personal_blog/login.html')elifrequest.method==
'POST':
dict=request.POST #获取POST请求参数
uname=dict.get('uname')#获取用户名
upwd=dict.get('upwd')#获取用户输入密码
ifusername==unameandupwd==password:
如果接收到的帐号密码与初始设在的一样那么表示登录成功需要跳转到博客首页
#重定向
return HttpResponseRedirect('/blog/index/')
else:
#帐号或密码错误,重新返回登录模板,并将用户输入的账号密码当参数传递回
去。context={'iserror':'帐号或密码错误',
'uname':uname,
}
重定向状态码: 302
重定向简写函数 redirect redirect被定义在django.shortcuts中
fromdjango.shortcuts import redirect
将HttpResponseRedirect 修改成redirect
return redirect('/blog/index/')
redirect 用法跟HttpResponseRedirect一样
6 、 URLconfname 在视图中的应用
URLconf中的name参数也可以在视图中使用,在重定向的时候,需要用的url,那么name参数也可以用在重定向的。
reverse(viewname, args=(参数,)) viewname是您要解析的网址路径。args是参数元祖
导入reverse函数
fromdjango.core.urlresolvers import reverse
例如上面重定向的url可以不写固定url,利用name参数动态解析
def login(request):
初始帐 号密码
usernam e = '老 狗'
passwor d = '123456
ifrequest.method=='GET':
returnrender(request,
'personal_blog/login.html')elif
request.method=='POST':
dict=request.POST #获取POST请求参数
uname=dict.get('uname')#获取用户名
upwd=dict.get('upwd')#获取用户输入密码
ifusername==unameandupwd==password:
'''如果接收到的帐号密码与初始设在的一样那么表示登录成功需要跳转到
博客首页'''return HttpResponseRedirect(reverse('index'))
else:
帐号或密码错误,重新返回登录模板,并将用户输入的账号密码当参数传递回去。
context={'iserror':'帐号
或密码错误',
'uname':uname,
'upwd':upwd
四、Session
对于敏感、重要的信息不能存在浏览器,也就不能使用cookie,如用户名、余额、等级、验证码等信息如何确
保数据的安全性呢,那就是将数据保存在服务端。这就利用到session技术。
Session对象存储特定用户会话所需的属性及配置信息。这样,当用户在应用程序的Web页之间跳转时,存储
在Session对象中的变量将不会丢失,而是在整个用户会话中一直存在下去。当用户请求来自应用程序的Web
页时,如果该用户还没有会话,则Web 服务器将自动创建一个Session对象。当会话过期或被放弃后,服务
器将终止该会话。
1 、启用 Session
django项目默认启用Session: settings.py文件,在项MIDDLEWARE_CLASSES中启用Session中间件
存储方式:设置SESSION_ENGINE项指定Session数据存储的方式,可以存储在数据库、缓存、Redis等存储在数
据库中,如下设置可以写,也可以不写,这是默认存储方式
SESSION_ENGINE='django.contrib.sessions.backends.db'
存储在缓存中:存储在本机内存中,如果丢失则不能找回,比数据库的方式读写更快
SESSION_ENGINE='django.contrib.sessions.backends.cache'
混合存储:优先从本机内存中存取,如果没有则从数据库中存取
SESSION_ENGINE='django.contrib.sessions.backends.cached_db'
如果存储在数据库中,需要在项INSTALLED_APPS中安装Session应用
django中默认的session保存在数据库,迁移之后会默认生成django_session表
Session包括三个数据:键,值,过期时间
Session依赖于Cookie
所有请求者的Session都会存储在服务器中,启用Session后,会在Cookie中存储一个sessionid,每次请求时浏览器都
会将这个数据发给服务器,服务器在接收到sessionid后,会根据这个值找出这个请求者的Session。所以如果想要
使用session,浏览器必须支持cookie,一般浏览器都会开启cookie,除非是人为关闭。
2 、 Session 方法
通过HttpRequest对象的Session属性进行会话的读写操作 以键值对的格式写会话 设置session值:
request.session['键']=值
根据键读取值
request.session.get('键',默认值)
清除所有会话,删除值部分
request.session.clear()
清除会话数据,删除会话的整条数据
request.session.flush()
删除会话中的指定键及值,在存储中只删除某个键及对应的值
delrequest.session['键']
设置会话的超时时间,如果没有指定过期时间则两周后过期
request.session.set_expiry(value)
如果value是一个整数,会话将在value秒没有活动后过期如果value为 0 ,那么用户会话的session将在用户的浏
览器关闭时过期如果value为None,那么会话永不过期
在视图中设置session。
defset_session(request):
request.session['h 1 ']='python'#以键值对的方
式设置sessionrequest.session['h 2 ']='django'
request.session['h
3 ']='linux'
request.session['h
4 ']='java'
request.session.set_expiry( 60 * 60 )#设置过期时间为 60 * 60 秒
配置url
url(r'^set_session/$', views.set_session),
浏览器访问:http:// 127. 0. 0. 1 : 8000 /blog/set_session/
可以看到cookie中保存的sessionid跟数据库中保存的session_key有一条相同的。就是这个回话保存在数据库中的
session
数据库中保存的session采用base 64 编码,解码之后可以看到session保存的键值对:
获取session值
defget_session(request):
a=
request.session.g
et('h 1 ')return
删除session
defdelete_session(request):
#delrequest.session['h 1 ']#删除键为h 1 的值
#request.session.clear() #清除session所有值,
但保留keyrequest.session.flush() #删除整个
session
returnHttpResponse('ok')
配置url
url(r'^delete_session/$', views.delete_session),
五、基于类的通用视图
在开发网站的过程中,有一些视图函数虽然处理的对象不同,但是其大致的代码逻辑是一样的。比如一个博客和一个
论坛,通常其首页都是展示一系列的文章列表或者帖子列表。对处理首页的视图函数来说,虽然其处理的对象一个是
文章,另一个是帖子,但是其处理的过程是非常类似的。先从数据库取出文章或者帖子列表,然后将这些数据传递给
模板并渲染模板。
Django把这些相同的逻辑代码抽取了出来,写成了一系列的通用视图函数,即基于类
的通用视图。类视图被封装在django.views.generic
先导入类视图
fromdjango.views.generic import ListView
1 、列表视图 ListView
在我们的博客应用中,index视图函数是从数据库中获取文章(Post)列表数据的: 博客首页的函数视图
defindex(request):
post_list=Post.post_object.all()
returnrender(request,'personal_blog/index.html',context={"post_list":post_list})
将index 视图函数改写为类视图
class IndexView(Lis tView):
model = Post templat
要写一个类视图,首先要继承django提供的类视图,这里是获取POST文章列表,继承ListView列表视图。列表视图
ListView就是用来获取模型类的列表数据,所以我们首页需要继承ListView.
model。将model指定为Post,告诉Django我要获取的模型是Post。
template_name。指定这个视图渲染的模板是 'personal_blog/index.html'。
context_object_name。指定获取的模型列表数据保存的变量名。这个变量会被传递给模板,相当于函数视图中的
context
参数。
直接看代码好像不好理解下面详细分析下:
1 、index视图函数首先通过Post.objects.all()从数据库中获取文章(Post)列表数据,并将其保存到post_list
变量中。在类视图中这个过程ListView已经帮我们做了。我们只需告诉ListView去数据库获取的模型是Post,即
指定model=Post
2 、将获得的模型数据列表保存到post_list 里,即指定context_object_name = ‘post_list’。
3 、然后渲染’personal_blog/index.html’ 模板文件,index视图函数中使用render函数。但这个过程
ListView已经帮我们做了,我们只需指定渲染哪个模板即可。
配置url,函数视图的url跟类视图url有所区别,IndexView是一个类,不能直接替代index函数需要先将类视
图转换成函数视图,调用类视图的 as_view() 方法.
#url(r'^index/$',views.index,name='index'),#函数视图
url(r'^index/$',views.IndexView.as_view(),name='index'),#类视图
配置好后,访问首页效果跟函
数视图一样。重写detail函数视
图为类视图。
class
MyDetailView(IndexView
):
template_name=
'personal_blog/detail.html'
context_object_name='post'
配置url
#url(r'^detail/(\d+)/',views.detail,name='detail'),
url(r'^detail/(\d+)/',views.MyDetailView.as_view(),name='detail'),
详细页视图函数的功能也是从数据库中获取文章列表数据,不过其和index视图函数不同的是,它获取的是某一
篇文章的详细信息。跟index视图区别就在于,需要从url中提取文章id参数。
参数说明:在类视图中,从URL捕获的命名组参数值保存在实例的kwargs属性(是一个字典)里,非命名参数值
按位置顺序保存在实例的args属性(是一个列表)里。所以在类视图中要获取文章id使用self.args[ 0 ]
调用父类的get_queryset 方法获得全部文章列表在使用get方法获取
指定id的文章。由于模板不一样所以要覆盖template_name=
‘personal_blog/detail.html’
模板参数不一样所以要覆盖 context_object_name =’post’
使用类视图可以减少重复代码,因为类视图可以继承,我们这个例子代码量比较少看不出太大效果。
2 、添加额外的上下文
get_context_data 上下文管理方法
通常来说,get_context_data会将当前类中的上下文数据,合并父类中的上下文数据,传给模板。但前提是你调用
了父类的
get_context_data方法。
class
MyDetailView(IndexView)
:
template_name=
'personal_blog/detail.html'
context_object_name='post'
defget_queryset(self):
returnsuper(MyDetailView,self).get_queryset().get(id=self.args[ 0 ])
defget_context_data(self,**kwargs):
#调用父类的get_context_data方法
context=super(MyDetailView,self).get_context_data(**kwargs)
#添加上下文
context['username']=
'盖伦'returncontext
#返
回上下文
3 、处理表单基于类的视图
在讲重定向的时候,讲过一个模拟登录的例子。其中判断是提交数据,还是请求登录页面采用的是ifelse逻辑判
断,使用类视图会让登录逻辑控制更为简洁易读。
使用基于类的视图处理表单重写模拟登录的案例:
fromdjango.views.generic
importViewclass
LoginView(View):
#初始帐号密码
usernam
e='老
狗'
passwor
d=
' 123456
'
template_name='personal_blog/login.html'
#get请求将调用get方法
defget(self,request,*args,
if self.username==uname and upwd==self.password:
#登录成功
return
redirect('/blog/index/
')else:
#登录失败
context={'iserror':'帐号
或密码错误',
'uname':uname,
Original: https://blog.csdn.net/sinat_61909096/article/details/124285688
Author: 丶清子
Title: Python-Django-视图
原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/733302/
转载文章受原作者版权保护。转载请注明原作者出处!