Python-Django-视图

《 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中的模板文件而不再调用自带的模板。

Python-Django-视图

其他错误处理方式相同。

3 、自定义错误视图

Django中默认的错误视图对于大多数web应用已经足够了,但是如果你需要任何自定义行为,只要在你的URLconf
中指定下面的处理器(在其他任何地方设置它们不会有效)。

在应用下的urls.py中自定义错误视图。 handler 404 覆盖了page_not_found()视图:

404 自定义错误视图

    def my_page_not_found_view(request):
        '''404错误视图'''
        return HttpResponse('请求不存在')

访问错误url

Python-Django-视图

其他错误视图跟 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 —— 服务器的端口(是一个字符串)。

在浏览器中开发者工具->网络 中可以看到请求信息:

Python-Django-视图
示例:scheme,path,encoding:
def info(request):
HttpRequest对象属性
 str = '&#x8BF7;&#x6C42;&#x7684;&#x65B9;&#x6848;:%s<br>&#x8DEF;&#x5F84;:%s<br>&#x7F16;&#x7801;%s'(request.scheme,request.path,request.encoding)
 return HttpResponse(str)

Python-Django-视图
method 表示请求使用的HTTP方式创建三个视图:
def method1(request):
    return render(request,'personal_blog/method1.html')
 def method2(request):
    return HttpResponse(request.method) # &#x8FD4;&#x56DE;&#x8BF7;&#x6C42;&#x65B9;&#x5F0F;
 def method3(request):
    return HttpResponse(request.method) # &#x8FD4;&#x56DE;&#x8BF7;&#x6C42;&#x65B9;&#x5F0F;

配置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/">&#x65B9;&#x5F0F;&#x4E00;&#xFF1A;get</a>
  <br> 
   <br> <form method="post" action="/blog/method3/">
   <input type="submit" value="&#x65B9;&#x5F0F;&#x4E8C;&#xFF1A;post">
   </form>
   </body>
    </html>

浏览其中访问:http://127.0.0.1:8000/blog/method1/ 点击链接 方式一:get,转到method2,浏览器接收到请求方式’GET’

Python-Django-视图
点击链接 方式二:post, 转到method3,会出现拒绝访问。django默认开启 csrf 跨站请求伪造,后面会详细讲, 这里先将csrf关闭。
Python-Django-视图
将项目目录的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',
)

注释之后重新访问:

Python-Django-视图

META 一个标准的Python 字典,包含所有的HTTP头部。

defmetainfo(request):
m=request.META
str=''
&#x5C06;http&#x8BF7;&#x6C42;&#x5934;&#x62FC;&#x63A5;&#x8FD4;&#x56DE;&#x7ED9;&#x6D4F;&#x89C8;&#x5668;&#xFF0C;&#x67E5;&#x770B;http&#x8BF7;&#x6C42;&#x5934;&#x4FE1;&#x606F;
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/

Python-Django-视图

; 3 、 QueryDict 对象

在HttpRequest 对象中,GET 和POST 属性是django.http.QueryDict 的实例,它是一个自定义的类似字典的
类,用来处理同一个键带有多个值。与python字典不同,QueryDict类型的对象用来处理同一个键带有多个值
的情况

方法:get:根据键获取值,如果一个键同时拥有多个值将获取最后一个值,如果键不存在则返回None值,可以设置
默认值进行后续处理

getlist:根据键获取值,值以列表返回,可以获取指定键的所有值如果键不存在则返回空列表[],可以设置默认值
进行后续处理

这两个方法用于获取url? 号后面的参数

get():

dict=request.GET
dict.get('&#x952E;'&#xFF0C;'&#x9ED8;&#x8BA4;&#x503C;') # &#x5982;&#x679C;GET&#x53C2;&#x6570;&#x91CC;&#x6CA1;&#x6709;&#x8FD9;&#x4E2A;&#x952E;&#xFF0C;&#x90A3;&#x4E48;&#x5C06;&#x4F7F;&#x7528;&#x9ED8;&#x8BA4;&#x503C;&#x3002;&#x9ED8;&#x8BA4;&#x503C;&#x662F;&#x4E00;&#x4E2A;&#x53EF;&#x9009;&#x53C2;&#x6570;

getlist():

dict=request.GET
dict.getlist('&#x952E;'&#xFF0C;'&#x9ED8;&#x8BA4;&#x503C;') # &#x83B7;&#x53D6;&#x4E00;&#x952E;&#x591A;&#x503C;&#x7684;&#x60C5;&#x51B5;&#xFF0C;&#x8FD4;&#x56DE;&#x6307;&#x5B9A;&#x952E;&#x7684;&#x6240;&#x6709;&#x503C;&#x7684;&#x5217;&#x8868;

4 、 GET 属性

请求参数:在请求地址结尾使用?,之后以”键=值”的格式拼接,多个键值对之间以&连接例如:

https://www.baidu.com/s?ie=UTF-8&wd=pythonie=UTF-8&wd=python ?&#x4E4B;&#x540E;&#x7684;&#x5C31;&#x662F;&#x8BF7;&#x6C42;&#x53C2;&#x6570;

请求参数键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:&#x4E00;&#x952E;&#x4E00;&#x503C;



<ahref=" 2 blog get ?a="1" &b="2" &a="3" ">get 2 :&#x4E00;&#x952E;&#x591A;&#x503C;
</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#&#x83B7;&#x53D6;get&#x8BF7;&#x6C42;&#x7684;&#x53C2;&#x6570;&#xFF0C;&#x8FD4;&#x56DE;&#x4E00;&#x4E2A;QueryDict&#x5BF9;&#x50CF;a
=dict.get('a') #get&#x65B9;&#x6CD5;&#x83B7;&#x53D6;&#x503C;
b=dict.get('b')
c=dict.get('c','&#x6211;&#x662F;&#x9ED8;&#x8BA4;&#x503C;c')#&#x4E0D;&#x5B58;&#x5728;&#x952E;c,&#x4F7F;&#x7528;&#x9ED8;&#x8BA4;&#x503C;
returnHttpResponse('a:%s,b:%s&#xFF0C;c:%s'%(a,b,c))
defget 2 (request):
dict=request.GET#&#x83B7;&#x53D6;get&#x8BF7;&#x6C42;&#x7684;&#x53C2;&#x6570;&#xFF0C;&#x8FD4;&#x56DE;&#x4E00;&#x4E2A;QueryDict&#x5BF9;&#x50CF;
a=dict.getlist('a') #getlist&#x65B9;&#x6CD5;&#x83B7;&#x53D6;&#x4E00;&#x952E;&#x591A;&#x503C;&#x7684;&#x53C2;&#x6570;&#xFF0C;&#x8FD4;&#x56DE;&#x5217;&#x8868;
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不存在则使用默认值。

Python-Django-视图

点击get 2 :一键多值 视图接收到请求参数 a为多值,getlist返回包含所有值得列表。

Python-Django-视图

; 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>&#x8868;&#x5355;</title>

<body>
<formmethod="post"action=" 1 blog post ">
&#x59D3;&#x540D;&#xFF1A;<inputtype="text"name="uname">
&#x5BC6;&#x7801;&#xFF1A;<inputtype="password"name="upwd">
&#x6027;&#x522B;&#xFF1A;<inputtype="radio"name="ugender"value=" 1 ">&#x7537;
<inputtype="radio"name="ugender"value=" 0 ">&#x5973;
&#x7231;&#x597D;&#xFF1A;<inputtype="checkbox"name="uhobby"value="抽烟">&#x62BD;&#x70DF;
<inputtype="checkbox"name="uhobby"value="喝酒">&#x559D;&#x9152;
<inputtype="checkbox"name="uhobby"value="烫头">&#x70EB;&#x5934;
<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>

&#x59D3;&#x540D;&#xFF1A;{{uname}}

&#x5BC6;&#x7801;&#xFF1A;{{upwd}}

&#x6027;&#x522B;&#xFF1A;{{ugender}}


&#x7231;&#x597D;&#xFF1A;
{%forloveinuhobby%}
{{love}}
{%endfor%}

</body>

</htmllang="en">

创建视图接收post请求参数调用 post 1 .html模板,将post请求的参数传给模板渲染

defpost 1 (request):
p_dict=request.POST #&#x83B7;&#x53D6;post&#x8BF7;&#x6C42;&#x53C2;&#x6570;
uname=p_dict.get('uname')
upwd=p_dict.get('upwd')
ugender=
p_dict.get('ugender')
uhobby=p_dict.getlist('uhobby')#&#x7231;&#x597D;&#x662F;&#x4E00;&#x952E;&#x591A;&#x503C;&#xFF0C;&#x4F7F;&#x7528;getlist&#x65B9;&#x6CD5;&#x83B7;&#x53D6;&#x6240;&#x6709;&#x7231;&#x597D;
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&#xFF1A;&#x8868;&#x793A;&#x8FD4;&#x56DE;&#x7684;&#x5185;&#x5BB9;
charset&#xFF1A;&#x8868;&#x793A;response&#x91C7;&#x7528;&#x7684;&#x7F16;&#x7801;&#x5B57;&#x7B26;&#x96C6;&#xFF0C;&#x9ED8;&#x8BA4;&#x4E3A;utf- 8
status_code&#xFF1A;&#x8FD4;&#x56DE;&#x7684;HTTP&#x54CD;&#x5E94;&#x72B6;&#x6001;&#x7801;
content-type&#xFF1A;&#x6307;&#x5B9A;&#x8FD4;&#x56DE;&#x6570;&#x636E;&#x7684;&#x7684;MIME&#x7C7B;&#x578B;&#xFF0C;&#x9ED8;&#x8BA4;&#x4E3A;'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不存在则什么也不发生

3 、设置 cookie

创建视图设置cookie

def
set_cookie(request)
:
response=HttpResponse("&#x8BBE;&#x7F6E;
cookie")
response.set_cookie('username',
'admin')
response.set_cookie('password',' 123456 ',max_age= 60 * 60 * 12 )#&#x8BBE;&#x7F6E;&#x8D85;&#x65F6;&#x65F6;&#x95F4; 60 * 60 * 12 &#x79D2;

创建视图删除cookie

defdelete_cookie(request):
response=HttpResponse('&#x5220;&#x9664;cookie')
response.delete_cookie('password')#&#x5220;&#x9664;&#x952E;&#x4E3A;password&#x7684;
cookiereturnresponse

创建视图获取cookie

def
get_cookie(request):
cookie=request.COOKIES#&#x83B7;&#x53D6;
cookieusername=
cookie.get('username')password=
cookie.get('password')
response=HttpResponse('%s%s'%(username,password))# &#x5C06;&#x83B7;&#x53D6;&#x5230;&#x7684;cookie&#x8FD4;&#x56DE;
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列表为空

Python-Django-视图

访问: http://127. 0. 0. 1 : 8000 /blog/set_cookie/ 设置cookie

Python-Django-视图

访问:http:// 127. 0. 0. 1 : 8000 /blog/get_cookie/

Python-Django-视图

; 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 ">
&#x7528;&#x6237;&#x540D;&#xFF1A;<inputname="uname"value="{{uname}}">
&#x5BC6;&#x7801;&#xFF1A;<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)
:
#&#x5E10;&#x53F7;&#x5BC6;&#x7801;
username='&#x8001;
&#x72D7;'password=
' 123456 '
ifrequest.method=='GET':
returnrender(request,
'personal_blog/login.html')elifrequest.method==
'POST':
dict=request.POST #&#x83B7;&#x53D6;POST&#x8BF7;&#x6C42;&#x53C2;&#x6570;
uname=dict.get('uname')#&#x83B7;&#x53D6;&#x7528;&#x6237;&#x540D;
upwd=dict.get('upwd')#&#x83B7;&#x53D6;&#x7528;&#x6237;&#x8F93;&#x5165;&#x5BC6;&#x7801;
ifusername==unameandupwd==password:
&#x5982;&#x679C;&#x63A5;&#x6536;&#x5230;&#x7684;&#x5E10;&#x53F7;&#x5BC6;&#x7801;&#x4E0E;&#x521D;&#x59CB;&#x8BBE;&#x5728;&#x7684;&#x4E00;&#x6837;&#x90A3;&#x4E48;&#x8868;&#x793A;&#x767B;&#x5F55;&#x6210;&#x529F;&#x9700;&#x8981;&#x8DF3;&#x8F6C;&#x5230;&#x535A;&#x5BA2;&#x9996;&#x9875;
#&#x91CD;&#x5B9A;&#x5411;
return HttpResponseRedirect('/blog/index/')
else:
#&#x5E10;&#x53F7;&#x6216;&#x5BC6;&#x7801;&#x9519;&#x8BEF;,&#x91CD;&#x65B0;&#x8FD4;&#x56DE;&#x767B;&#x5F55;&#x6A21;&#x677F;&#xFF0C;&#x5E76;&#x5C06;&#x7528;&#x6237;&#x8F93;&#x5165;&#x7684;&#x8D26;&#x53F7;&#x5BC6;&#x7801;&#x5F53;&#x53C2;&#x6570;&#x4F20;&#x9012;&#x56DE;
&#x53BB;&#x3002;context={'iserror':'&#x5E10;&#x53F7;&#x6216;&#x5BC6;&#x7801;&#x9519;&#x8BEF;',
'uname':uname,
}

重定向状态码: 302

Python-Django-视图

重定向简写函数 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):
&#x521D;&#x59CB;&#x5E10; &#x53F7;&#x5BC6;&#x7801;
usernam e = '&#x8001; &#x72D7;'
passwor d = '123456
ifrequest.method=='GET':
returnrender(request,
'personal_blog/login.html')elif
request.method=='POST':
dict=request.POST #&#x83B7;&#x53D6;POST&#x8BF7;&#x6C42;&#x53C2;&#x6570;
uname=dict.get('uname')#&#x83B7;&#x53D6;&#x7528;&#x6237;&#x540D;
upwd=dict.get('upwd')#&#x83B7;&#x53D6;&#x7528;&#x6237;&#x8F93;&#x5165;&#x5BC6;&#x7801;
ifusername==unameandupwd==password:
'''&#x5982;&#x679C;&#x63A5;&#x6536;&#x5230;&#x7684;&#x5E10;&#x53F7;&#x5BC6;&#x7801;&#x4E0E;&#x521D;&#x59CB;&#x8BBE;&#x5728;&#x7684;&#x4E00;&#x6837;&#x90A3;&#x4E48;&#x8868;&#x793A;&#x767B;&#x5F55;&#x6210;&#x529F;&#x9700;&#x8981;&#x8DF3;&#x8F6C;&#x5230;
&#x535A;&#x5BA2;&#x9996;&#x9875;'''return HttpResponseRedirect(reverse('index'))
else:
&#x5E10;&#x53F7;&#x6216;&#x5BC6;&#x7801;&#x9519;&#x8BEF;,&#x91CD;&#x65B0;&#x8FD4;&#x56DE;&#x767B;&#x5F55;&#x6A21;&#x677F;&#xFF0C;&#x5E76;&#x5C06;&#x7528;&#x6237;&#x8F93;&#x5165;&#x7684;&#x8D26;&#x53F7;&#x5BC6;&#x7801;&#x5F53;&#x53C2;&#x6570;&#x4F20;&#x9012;&#x56DE;&#x53BB;&#x3002;
context={'iserror':'&#x5E10;&#x53F7;
&#x6216;&#x5BC6;&#x7801;&#x9519;&#x8BEF;',
'uname':uname,
'upwd':upwd

四、Session

对于敏感、重要的信息不能存在浏览器,也就不能使用cookie,如用户名、余额、等级、验证码等信息如何确
保数据的安全性呢,那就是将数据保存在服务端。这就利用到session技术。

Session对象存储特定用户会话所需的属性及配置信息。这样,当用户在应用程序的Web页之间跳转时,存储
在Session对象中的变量将不会丢失,而是在整个用户会话中一直存在下去。当用户请求来自应用程序的Web
页时,如果该用户还没有会话,则Web 服务器将自动创建一个Session对象。当会话过期或被放弃后,服务
器将终止该会话。

1 、启用 Session

django项目默认启用Session: settings.py文件,在项MIDDLEWARE_CLASSES中启用Session中间件

Python-Django-视图
存储方式:设置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应用

Python-Django-视图
django中默认的session保存在数据库,迁移之后会默认生成django_session表
Python-Django-视图

Session包括三个数据:键,值,过期时间

Python-Django-视图

Session依赖于Cookie

所有请求者的Session都会存储在服务器中,启用Session后,会在Cookie中存储一个sessionid,每次请求时浏览器都
会将这个数据发给服务器,服务器在接收到sessionid后,会根据这个值找出这个请求者的Session。所以如果想要
使用session,浏览器必须支持cookie,一般浏览器都会开启cookie,除非是人为关闭。

2 、 Session 方法

通过HttpRequest对象的Session属性进行会话的读写操作 以键值对的格式写会话 设置session值:

request.session['&#x952E;']=&#x503C;

根据键读取值

request.session.get('&#x952E;',&#x9ED8;&#x8BA4;&#x503C;)

清除所有会话,删除值部分

request.session.clear()

清除会话数据,删除会话的整条数据

request.session.flush()

删除会话中的指定键及值,在存储中只删除某个键及对应的值

delrequest.session['&#x952E;']

设置会话的超时时间,如果没有指定过期时间则两周后过期

request.session.set_expiry(value)

如果value是一个整数,会话将在value秒没有活动后过期如果value为 0 ,那么用户会话的session将在用户的浏
览器关闭时过期如果value为None,那么会话永不过期

在视图中设置session。

defset_session(request):
request.session['h 1 ']='python'#&#x4EE5;&#x952E;&#x503C;&#x5BF9;&#x7684;&#x65B9;
&#x5F0F;&#x8BBE;&#x7F6E;sessionrequest.session['h 2 ']='django'
request.session['h
3 ']='linux'
request.session['h
4 ']='java'
request.session.set_expiry( 60 * 60 )#&#x8BBE;&#x7F6E;&#x8FC7;&#x671F;&#x65F6;&#x95F4;&#x4E3A; 60 * 60 &#x79D2;

配置url

url(r'^set_session/$', views.set_session),

浏览器访问:http:// 127. 0. 0. 1 : 8000 /blog/set_session/

可以看到cookie中保存的sessionid跟数据库中保存的session_key有一条相同的。就是这个回话保存在数据库中的
session

Python-Django-视图
Python-Django-视图

数据库中保存的session采用base 64 编码,解码之后可以看到session保存的键值对:

Python-Django-视图

获取session值

defget_session(request):
a=
request.session.g
et('h 1 ')return

删除session

defdelete_session(request):
#delrequest.session['h 1 ']#&#x5220;&#x9664;&#x952E;&#x4E3A;h 1 &#x7684;&#x503C;
#request.session.clear() #&#x6E05;&#x9664;session&#x6240;&#x6709;&#x503C;&#xFF0C;
&#x4F46;&#x4FDD;&#x7559;keyrequest.session.flush() #&#x5220;&#x9664;&#x6574;&#x4E2A;
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&#x3002;&#x5C06;model&#x6307;&#x5B9A;&#x4E3A;Post&#xFF0C;&#x544A;&#x8BC9;Django&#x6211;&#x8981;&#x83B7;&#x53D6;&#x7684;&#x6A21;&#x578B;&#x662F;Post&#x3002;
template_name&#x3002;&#x6307;&#x5B9A;&#x8FD9;&#x4E2A;&#x89C6;&#x56FE;&#x6E32;&#x67D3;&#x7684;&#x6A21;&#x677F;&#x662F; 'personal_blog/index.html'&#x3002;
context_object_name&#x3002;&#x6307;&#x5B9A;&#x83B7;&#x53D6;&#x7684;&#x6A21;&#x578B;&#x5217;&#x8868;&#x6570;&#x636E;&#x4FDD;&#x5B58;&#x7684;&#x53D8;&#x91CF;&#x540D;&#x3002;&#x8FD9;&#x4E2A;&#x53D8;&#x91CF;&#x4F1A;&#x88AB;&#x4F20;&#x9012;&#x7ED9;&#x6A21;&#x677F;&#xFF0C;&#x76F8;&#x5F53;&#x4E8E;&#x51FD;&#x6570;&#x89C6;&#x56FE;&#x4E2D;&#x7684;
context
&#x53C2;&#x6570;&#x3002;

直接看代码好像不好理解下面详细分析下:

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'),#&#x51FD;&#x6570;&#x89C6;&#x56FE;
url(r'^index/$',views.IndexView.as_view(),name='index'),#&#x7C7B;&#x89C6;&#x56FE;

配置好后,访问首页效果跟函

数视图一样。重写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):
#&#x8C03;&#x7528;&#x7236;&#x7C7B;&#x7684;get_context_data&#x65B9;&#x6CD5;
context=super(MyDetailView,self).get_context_data(**kwargs)
#&#x6DFB;&#x52A0;&#x4E0A;&#x4E0B;&#x6587;
context['username']=
'&#x76D6;&#x4F26;'returncontext
#&#x8FD4;
&#x56DE;&#x4E0A;&#x4E0B;&#x6587;

3 、处理表单基于类的视图

在讲重定向的时候,讲过一个模拟登录的例子。其中判断是提交数据,还是请求登录页面采用的是ifelse逻辑判
断,使用类视图会让登录逻辑控制更为简洁易读。

使用基于类的视图处理表单重写模拟登录的案例:

fromdjango.views.generic
importViewclass
LoginView(View):
#&#x521D;&#x59CB;&#x5E10;&#x53F7;&#x5BC6;&#x7801;
usernam
e='&#x8001;
&#x72D7;'
passwor
d=
' 123456
'
template_name='personal_blog/login.html'
#get&#x8BF7;&#x6C42;&#x5C06;&#x8C03;&#x7528;get&#x65B9;&#x6CD5;
defget(self,request,*args,
if self.username==uname and upwd==self.password:
#&#x767B;&#x5F55;&#x6210;&#x529F;
return
redirect('/blog/index/
')else:
#&#x767B;&#x5F55;&#x5931;&#x8D25;
context={'iserror':'&#x5E10;&#x53F7;
&#x6216;&#x5BC6;&#x7801;&#x9519;&#x8BEF;',
'uname':uname,

Original: https://blog.csdn.net/sinat_61909096/article/details/124285688
Author: 丶清子
Title: Python-Django-视图

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/733302/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球