三、Django视图

  视图负责接收Web请求HttpRequest,进行逻辑处理,返回Web响应HttpResponse给请求者。

1、使用视图

  使用视图时需要进行两方面操作:

  (1)在"应用/views.py"中定义视图

  (2)配置URLconf,将视图函数和url对应起来

2、URLconf

  用户通过在浏览器的地址栏中输入网址请求网站,对于Django开发的网站,由哪一个视图进行处理请求,是由url匹配找到的。

  2.1 配置

    (1)在settings.py中通过ROOT_URLCONF指定url配置,默认已经有此配置。

      

 

 

     (2)打开settings.py同级文件urls.py可以看到默认配置

      

 

 

     (3)注意点:

        1)在settings.py同级文件urls.py中包含配置,在各自应用中创建具体配置。

        2)定义urlpatterns列表,存储url()对象,这个名称是固定的。

          urlpatterns中的每个正则表达式在第一次访问它们时被编译,这使得运行很快。

  2.2 语法

    url()对象,被定义在django.conf.urls包中,有两种语法结构:

    (1)语法一

      包含,一般在自定义应用中创建一个urls.py定义url。

      这种语法用于在settings.py同级文件urls.py中,目的是将应用的urls配置到应用内部,数据更清晰并且易于维护。

      url(正则,include('应用.urls'))

    (2)语法二

      定义,指定URL和视图函数的对应关系。

      在应用内部创建urls.py文件,指定请求地址与视图的对应关系。

      url(正则,'视图函数名称')

    说明:(1)正则部分推荐使用r,表示字符串不转义,这样在正则表达式中使用“\”只写一个就可以

       (2)不能在开始加反斜杠,推荐在结束加反斜杠。

  2.3 获取值

    请求的url被看做是一个普通的python字符串,进行匹配时不包括域名、get或post参数。

    如请求地址为:http://127.0.0.1:8000/delete1/?a=1

    (1)去除掉域名和参数部分,并将最前面的/去除后,只剩下如下部分与正则匹配:create1/

    (2)在booktest/urls.py文件中,定义与这个地址匹配的url如下:

      url(r'^delete1\d+/$',views.show_arg),

    (3)在booktest/views.py中创建视图show_arg

      def show_arg(request):

        return HttpResponse('show_arg')

    可以在匹配过程中从url中捕获参数,每个捕获的参数都作为一个普通的python字符串传递给视图。

    获取值需要在正则表达式中使用小括号,分为两种方式:位置参数;关键字参数。

    注意:两种参数的方式不要混合使用,在一个正则表达式中只能使用一种参数方式。

    方法一:位置参数

    直接使用小括号,通过位置参数传递给视图

    1)为了提取参数,修改上面的正则表达式如下:

      url(r'^delete(\d+)/$',views.show_arg),

    2)修改视图show_arg如下:

      def show_arg(request,id):

        return HttpResponse('show arg %s' % id)

    3)浏览器效果

    

    方法二:关键字参数

    在正则表达式部分为组命名。

    1)修改正则表达式如下:

      url(r'^delete(?P<id1>\d+)/$',views.show_arg),

    2)修改视图show_arg如下:

      def show_arg(request,id1):

        return HttpResponse('show %s' %id1)

      注意:视图show_arg此时必须要有一个参数名为id1,否则会报错。

3、视图

  视图就是python中的函数,视图一般被定义在'应用/views.py'文件中。视图必须返回一个HttpResponse对象或子对象作为响应。

  响应可以是一张网页的HTML内容,一个重定向,一个404错误等。

  视图的第一个参数必须为HttpRequest实例,还可能包含参数如:

  (1)通过正则表达式组获得的关键字参数

  (2)通过正则表达式组获取的位置参数

  3.1内置错误视图

    Django内置处理HTTP错误的视图,主要错误及视图包括:

    (1)404错误:page not found视图

    (2)500错误:server error视图

    如果想看到错误视图而不是调试信息,需要修改setting.py文件的DEBUG项。

      DEBUG=False

      ALLOWED_HOSTS=[ '*', ]

  3.2 404错误及视图

    将请求地址进行url匹配后,没有找到匹配的正则表达式,则调用404视图,这个视图会调用404.html的模板进行渲染。视图传递变量request_path给模板,表示导致错误的URL。

    404.html模板可以自行定义,放置在templates目录下。

  3.3 500错误及视图

    在视图中代码运行报错会发生500错误,调用内置错误视图,使用templates/500.html模板渲染。

4、HttpRequest对象

  服务器接收到http协议的请求后,会根据报文创建HttpRequest对象,这个对象不需要我们创建,直接使用服务器构造好的对象就可以。

  视图的第一个参数必须是HttpRequest对象,在django.http模块中定义了HttpRequest对象的API

  4.1 属性

  在视图中通过request.属性来调用

  (1)path:一个字符串,表示请求的页面的完整路径,不包含域名和参数部分。

  (2)method:一个字符串,表示请求使用的HTTP方法,常用值包括:'GET'、'POST'。

    1)在浏览器中给出地址发出请求采用get方式,如超链接。

    2)在浏览器中点击表单的提交按钮发起请求,如果表单的method设置为post则为post请求。

  (3)encoding:一个字符串,表示提交的数据的编码方式。

    1)如果为None则表示使用浏览器的默认设置,一般为utf-8

    2)这个属性是可写的,可以通过修改它来修改访问表单数据使用的编码,接下来对属性的任何访问将使用新的encoding值

  (4)GET:QueryDict类型对象,类似于字典,包含get请求方式的所有参数。

  (5)POST:QueryDict类型对象,类似于字典,包含post请求方式的所有参数。

  (6)FILES:一个类似于字典的对象,包含所有的上传文件。

  (7)COOKIES:一个标准的Python字典,包含所有的cookie,键和值都为字符串。

  (8)session:一个既可读又可写的类似于字典的对象,表示当前的会话,只有当Django 启用会话的支持时才可用。

  4.2 QueryDict对象

  (1)定义在django.http.QueryDict

  (2)HttpRequest对象的属性GET、POST都是QueryDict类型的对象

  (3)与python字典不同,QueryDict类型的对象用来处理同一个键带有多个值的情况

  (4)方法get():根据键获取值

  (5)如果一个键同时拥有多个值将获取最后一个值

  (6)如果键不存在则返回None值,可以设置默认值进行后续处理

      dict.get('键',默认值)

      可简写为

      dict['键']

  (7)方法getlist():根据键获取值,值以列表返回,可以获取指定键的所有值

  (8)如果键不存在则返回空列表[],可以设置默认值进行后续处理

      dict.getlist(‘键’,默认值)

  4.3 GET属性

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

    例如网址:http://www.baidu.com/?a=10&b=20&c=python

    其中的请求参数为:a=10&b=20&c=python

    (1)分析请求参数,键为'a'、'b'、'c',值为'10'、'20'、'python'。

    (2)在Django中可以使用HttpRequest对象的GET属性获得get方式请求的参数。

    (3)GET属性是一个QueryDict类型的对象,键和值都是字符串类型。

    (4)键是开发人员在编写代码时确定下来的

    (5)值是根据数据生成的。

  4.4 POST属性

    使用form表单请求时,method方式为post则会发起post方式的请求,需要使用HttpRequest对象的POST属性接收参数,POST属性是一个QueryDict类型的对象。

    问:表单from如何提交参数呢?

    答:表单控件name属性的值作为键,value属性的值为值,构成键值对提交。

      (1)如果表单控件没有name属性则不提交

      (2)对于checkbox控件,name属性的值相同为一组,被选中的项会被提交,出现一键多值的情况

      (3)键是表单控件name属性的值,是由开发人员编写的

      (4)值是用户填写或选择的

5、HttpResponse对象

  视图在接收请求并处理后,必须返回HttpResponse对象或子对象。在django.http模块中定义了HttpResponse对象的API。HttpRequest对象由Django创建,HttpResponse对象由开发人员创建。

  5.1 属性

  (1)content:表示返回的内容。

  (2)charset:表示response采用的编码字符集,默认为utf-8。    

  (3)status_code:返回的HTTP响应状态码

  (4)content-type:指定返回数据的的MIME类型,默认为'text/html'

  5.2 方法

  (1)__init__:创建HttpResponse对象后完成返回内容的初始化

  (2)set_cookie:设置Cookie信息

    set_cookie(key,vlaue=' ',max_age=None,expires=None)

  (3)cookie是网站以键值对格式存储在浏览器中的一段纯文本信息,用于实现用户跟踪

    1)max_age是一个整数,表示在指定秒数后过期

    2)expires是一个datetime或timedelta对象,会话将在这个指定的日期/时间过期

    3)max_age与expires二选一

    4)如果不指定过期时间,在关闭浏览器时cookie会过期

  (4)delete_cookie(key):删除指定的key的Cookie,如果key不存在则什么也不发生

  (5)write:向响应体中写数据

  5.3 子类JsonResponse

    在浏览器中使用javascript发起ajax请求时,返回json格式的数据,此处以jquery的get()方法为例。类JsonResponse继承自HttpResponse对象,被定义在django.http模块中,创建对象时接收字典作为参数

    JsonResponse对象的content-type为'application/json'。

  5.4 子类HttpResponseRedirect

    当一个逻辑处理完成后,不需要向客户端呈现数据,而是转回到其它页面,如添加成功、修改成功、删除成功后显示数据列表,而数据的列表视图已经开发完成,此时不需要重新编写列表的代码,而是转到这个视图就可以,此时就需要模拟一个用户请求的效果,从一个视图转到另外一个视图,就称为重定向。

    Django中提供了HttpResponseRedirect对象实现重定向功能,这个类继承自HttpResponse,被定义在django.http模块中,返回的状态码为302。

    5.4.1 重定向简写函数redirect

      在django.shortcuts模块中为重定向类提供了简写函数redirect。

6、状态保持

  浏览器请求服务器是无状态的。无状态指一次用户请求时,浏览器、服务器无法知道之前这个用户做过什么,每次请求都是一次新的请求。无状态的应用层面的原因是:浏览器和服务器之间的通信都遵守HTTP协议。根本原因是:浏览器与服务器是使用Socket套接字进行通信的,服务器将请求结果返回给浏览器之后,会关闭当前的Socket连接,而且服务器也会在处理页面完毕之后销毁页面对象。

  有时需要保存下来用户浏览的状态,比如用户是否登录过,浏览过哪些商品等。 实现状态保持主要有两种方式:(1)在客户端存储信息使用Cookie(2)在服务器端存储信息使用Session

  6.1 Cookie

    Cookie,有时也用其复数形式Cookies,指某些网站为了辨别用户身份、进行session跟踪而储存在用户本地终端上的数据(通常经过加密)。

    Cookie是由服务器端生成,发送给User-Agent(一般是浏览器),浏览器会将Cookie的key/value保存到某个目录下的文本文件内,下次请求同一网站时就发送该Cookie给服务器(前提是浏览器设置为启用cookie)。Cookie名称和值可以由服务器端开发自己定义,这样服务器可以知道该用户是否是合法用户以及是否需要重新登录等。服务器可以利用Cookies包含信息的任意性来筛选并经常性维护这些信息,以判断在HTTP传输中的状态。Cookies最典型记住用户名。

    Cookie的特点

    (1)Cookie以键值对的格式进行信息的存储。

    (2)Cookie基于域名安全,不同域名的Cookie是不能互相访问的

    (3)当浏览器请求某网站时,会将浏览器存储的跟网站相关的所有Cookie信息提交给网站服务器。

    设置Cookie

    (1)创建视图cookie_set

def cookie_set(request):
    response = HttpResponse("<h1>设置Cookie,请查看响应报文头</h1>")
    response.set_cookie('h1', '你好')
    return response

    读取Cookie

      Cookie信息被包含在请求头中,使用request对象的COOKIES属性访问。

    (1)创建视图cookie_get

def cookie_get(request):
    response = HttpResponse("读取Cookie,数据如下:<br>")
    if 'h1' in request.COOKIES:
        response.write('<h1>' + request.COOKIES['h1'] + '</h1>')
    return response

  6.2 Session

    对于敏感、重要的信息,建议要储在服务器端,不能存储在浏览器中,如用户名、余额、等级、验证码等信息。

    在服务器端进行状态保持的方案就是Session。

    6.2.1 启用Session

      Django项目默认启用Session。

      settings.py文件中,在项MIDDLEWARE_CLASSES中启用Session中间件。

      

 

       禁用Session:将Session中间件删除

    6.2.2 存储方式

      settings.py文件,设置SESSION_ENGINE项指定Session数据存储的方式,可以存储在数据库,缓存,Redis等。

      (1)存储在数据库中,如下设置可以写,也可以不写,这是默认存储方式。

         SESSION_ENGINE='django.contrib.sessions.backends.db'

      (2)存储在缓存中:存储在本机内存中,如果丢失则不能找回,比数据库的方式读写更快

         SESSION_ENGINE='django.contrib.sessions.backends.cache'

      (3)混合存储:优先从本机内存中存取,如果没有则从数据库中存取。

         SESSION_ENGINE='django.contrib.sessions.backends.cached_db'

      (4)如果存储在数据库中,需要在项INSTALLED_APPS中安装Session应用

        

 

      (5)迁移后会在数据库中创建出存储Session的表

        

 

       (6)表结构如下图。

        

 

     6.2.3 Session依赖于Cookie

      所有请求者的Session都会存储在服务器中,服务器如何区分请求者和Session数据的对应关系呢?

      答:在使用Session后,会在Cookie中存储一个sessionid的数据,每次请求时浏览器都会将这个数据发给服务器,服务器在接收到sessionid后,会根据这个值找出这个请求者的Session。

      结果:如果想使用Session,浏览器必须支持Cookie,否则就无法使用Session了。

      存储Session时,键与Cookie中的sessionid相同,值是开发人员设置的键值对信息,进行了base64编码,过期时间由开发人员设置。

    6.2.4 对象及方法

      通过HttpRequest对象的session属性进行会话的读写操作。

      (1) 以键值对的格式写session。

         request.session['键']=值

      (2)根据键读取值

         request.session.get('键',默认值)

      (3)清除所有session,在存储中删除值部分。

         request.session.clear()

      (4)清除session数据,在存储中删除session的整条数据。

         request.session.flush()

      (5)删除session中的指定键及值,在存储中只删除某个键及对应的值

         del request.session['键']

      (6)设置会话的超时时间,如果没有指定过期时间则两个星期后过期

         request.session.set_expiry(value)

        1)如果value是一个整数,会话将在value秒没有活动后过期

        2)如果value为0,那么用户会话的Cookie将在用户的浏览器关闭时过期

        3)如果value为None,那么会话永不过期

posted @ 2020-04-21 23:45  Norni  阅读(113)  评论(0编辑  收藏  举报