Django-视图

概述

  • 作用
    • 接收Web请求并返回web响应
  • 本质
    • 就是一个Python函数,被定义在views.py文件中
  • 响应
    • 可以是一个网页的HTML内容、一个重定向、数据、一个404错误等等
  • 过程
    过程图

URLconf

  • 指定根级url配置文件

    • settings.py文件中的ROOT_URLCONF
  • 指定子路由

    • 在应用下创建子路由urls.py文件
    • 在主路由中引用
      1
      2
      3
      4
      5
      urlpatterns = [
      url(r'^admin/', admin.site.urls),
      # namespace表示命名空间
      url(r'^', include('myApp.urls', namespace="sunck")),
      ]
  • urlpatterns

    • 一个RegexURLResolver实例的列表
    • url()参数
      • 正则表达式
      • 视图函数
      • 名称
        1
        url(r'^$', views.index, name="index"), 

视图函数

  • 定义视图

    • 本质:一个函数

    • 视图参数:

      • 一个HTTPRequest对象

      • 通过正则表达式组获取的位置参数

        如果路由带有正则表达式组,在定义视图函数时,要对应用形参接收

      • 通过正则表达式组获取的关键字参数

    • 位置:应用目录下的views.py文件中

    • 说明:如果处理的功能过多,可以将视图定义在不同的py文件中

  • 错误视图

    • 404

      • templates目录下创建名为404.html文件
        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        <!DOCTYPE html>
        <html lang="en">
        <head>
        <meta charset="UTF-8">
        <title>公益404</title>
        </head>
        <body>
        <script src="//qzonestyle.gtimg.cn/qzone/hybrid/app/404/search_children.js"
        charset="utf-8" homePageUrl="/" homePageName="返回首页">
        </script>
        </body>
        </html>
      • 修改settions.py文件
        1
        2
        3
        DEBUG = False

        ALLOWED_HOSTS = ["*",]

        当为True时永远不会使用404页面

    • 500

      • 在视图代码中出现运行时错误
    • 400

      • 错误来自客户端的操作
      • 当用户进行的操作在安全方面可以的时候,例如篡改会话cookie

HttpRequest对象

  • 概述:

    • 服务器收到http协议的请求后,会根据报文创建HTTPRequest对象
    • 视图函数的第一个参数时HTTPRequest对象
  • 属性

    • path字符串类型,表示请求的完整路径,不包含域名和端口
    • method字符串类型,表示使用的HTTP方法,常用的包括GET、POST
    • encoding字符串类型,表示提交数据的编码方式
      • 如果为None则表示使用浏览器默认的设置,一般为utf-8
      • 这个属性是可写的,可以通过修改它来修改方法表单数据的编码
    • GET一个类似字典的对象,包含了get请求方式的所有参数
    • POST一个类似字典的对象,包含了POST请求方式的所有参数
    • FILES一个类似字典的对象,包含的是所有的上传文件
    • COOKIES一个标准的python字典,包含所有的cookie,键和值都是字符串
    • session一个即可读又可写的类似于字典的对象,表示当前会话,只有Django启动会话才支持session属性
  • 方法

    • is_ajax()如果请求是通过XMLHttpRequest发起的,返回True
  • QueryDict对象

    • request对象的属性GET、POST都是QueryDict类型的对象
    • 与python字典不同,QueryDict类型的对象用来处理同一个键带有多个值的情况
    • get()
      • 功能:根据键获取值
      • 注意:只能获取一个值;如果一个键同时用过多个值,获取最后一个值
    • getlist()将键对应的值以列表的形式返回,可以获取一个键的多个值
  • GET属性

    • 127.0.0.1:8000/get1?a=1&b=2&c=3
      1
      2
      3
      4
      5
      def get1(request):
      a = request.GET.get("a")
      b = request.GET.get("b")
      c = request.GET.get("c")
      return HttpResponse(a + b + c)
    • 127.0.0.1:8000/get2?a=1&a=2&c=3
      1
      2
      3
      4
      def get2(request):
      alist = request.GET.getlist("a")
      c = request.GET.get("c")
      return HttpResponse(alist[0] + alist[1] + c)
  • POST属性

    • 使用表单提交,目前需要在settings.py中注释掉csrf

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      <!DOCTYPE html>
      <html lang="en">
      <head>
      <meta charset="UTF-8">
      <title>登陆</title>
      </head>
      <body>
      <form action="/login/" method="POST">
      {# {% csrf_token %}#}
      账号:<input type="text" value="" name="username"/><br/>
      密码:<input type="password" value="" name="passwd"/><br/>
      爱好:<input type="checkbox" value="power" name="hobby"/>权利
      <input type="checkbox" value="money" name="hobby"/>金钱
      <input type="checkbox" value="knowledge" name="hobby"/>知识<br/>
      <input type="submit" value="登陆"/>
      </form>
      </body>
      </html>
      1
      2
      3
      4
      5
      6
      7
      8
      9
      def login(request):
      if request.method == "GET":
      return render(request, "myApp/login.html")
      else:
      username = request.POST.get("username")
      passwd = request.POST.get("passwd")
      hobbys = request.POST.getlist("hobby")
      print(username, passwd, hobbys)
      return HttpResponse("收到用户信息")

HttpResponse对象

  • 概述:HttpRequest对象是由Django自动创建,HTTPResponse对象由程序员创建

  • 用法

    • 调用模板:render()函数
      • 原型:render(request, template_name, context=None)
      • 说明:结合一个给定模板和一个给定的上下文字典,并返回一个渲染后的HTTPResponse对象
      • 参数:
        • request:用于生成response
        • template_name:要使用的模板名称
        • context:传递个模板的数据
      • 应用:return render(request, "myApp/login.html")
    • 直接返回数据:return HttpResponse("收到用户信息")
  • 属性

    • content表示返回的内容,字符串类型
    • charset表示response采用的编码字符集,字符串类型
    • status_code响应的HTTP状态码
    • content_type指定输出的MIME类型
      1
      2
      3
      4
      5
      6
      7
      8
      def restest(request):
      response = HttpResponse()
      response.content = "sunck is a nice man"
      response.charset = "utf-8"
      response.status_code = 200
      response.content_type = "application/json"

      return response
  • 方法

    • init使用页面内容实例化HTTPResonance对象
    • write(content):以文本的方式写
    • flush()以文件的方式输出缓冲区
    • set_cookie(key, value, max_age=None, expires=None)设置cookie
    • dalete_cookie(key)删除指定cookie,如果删除的cookie不存在就当什么都没发生
  • 子类HttpResponseRedirect

    • 重定向,服务端跳转
      1
      2
      3
      def index1(request):
      # 路由重定向
      return HttpResponseRedirect('/')
    • 简写方式:redirect()
      • 原型:redirect(to, *args, **kwargs)
      • 实现:
        1
        2
        3
        4
        def index1(request):
        # 路由重定向
        # return HttpResponseRedirect('/')
        return redirect("/")
      • 注意:to推荐使用反向解析
  • 子类JsonResponse

    • 返回Json数据,一般用于ajax异步请求
    • JsonResponse的对象的Content-Type值默认为application/json

状态保持

  • 概述:

    • http协议是无状态,每次请求都是一次新的请求,不会记得之前的通信状态
    • 客户端与服务端的一次通信就是一次会话
    • 实现状态保持的方式:在客户端或服务端存储会话的有关数据
    • 存储方式:
      • cookie
      • session:会话一般指的是session对象
    • 使用cookie,所有的数据存储在客户端,在客户端不要存储敏感信息
    • 推荐使用session方式,所有的数据存储在服务端,在客户端cookie中存储session_id
    • 状态保持的目的:在一段时间内跟踪请求者的状态,可以实现跨页面的访问请求者的数据
    • 注意:不同的请求者之间不会共享数据,与请求者一一对应的
  • 启用session:settings.py文件

    • INSTALLED_APPS
      1
      'django.contrib.sessions',
    • MIDDLEWARE
      1
      'django.contrib.sessions.middleware.SessionMiddleware',
  • 使用session

    • 启用会话后,每个HTTPRequest对象将具有一个session属性,它是一个类似字典的对象
    • 取值:
      • get(key, default=None)
      • 根据键获取会话的值
    • 删除:
      • clear():清除所有会话
      • flush():删除当前会话数据,并且删除cookie
      • del request.session['键名']:删除一个会话
  • 示例

    1
    2
    3
    4
    5
    # 状态保持
    url(r'^home/$', views.home),
    url(r'^cart/$', views.cart),
    url(r'^login/$', views.login),
    url(r'^quit/$', views.quit),
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    from django.shortcuts import render, redirect


    def home(request):
    username = request.session.get("username", default="未登录")
    return render(request, 'myApp/home.html', {"username": username})


    def cart(request):
    username = request.session.get("username", default="未登录")
    return render(request, 'myApp/cart.html', {"username": username})


    def login(request):
    if request.method == "GET":
    fromPath = request.GET.get("from")
    return render(request, 'myApp/login.html', {"from": fromPath})
    else:
    username = request.POST.get("username")
    passwd = request.POST.get("passwd")
    url = request.GET.get("from")
    if username == "sunck" and passwd == "123qweasdzxc":
    # 登陆验证成功
    # 将用户名存储到session中
    request.session["username"] = username
    url = "/" + url + "/"
    response = redirect(url)

    # 设置cookie
    response.set_cookie("token", "123456")

    return response
    else:
    # 登陆验证失败
    url = "/login/?from=" + url
    return redirect(url)


    from django.contrib.auth import logout


    def quit(request):
    logout(request)
    return redirect('/home/')
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    <!DOCTYPE html>
    <html lang="en">
    <head>
    <meta charset="UTF-8">
    <title>home</title>
    </head>
    <body>
    <h1>home欢迎:{{ username }}</h1>
    <a href="/login/?from=home">登陆</a>
    <a href="/quit/">退出</a>
    </body>
    </html>
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    <!DOCTYPE html>
    <html lang="en">
    <head>
    <meta charset="UTF-8">
    <title>登陆</title>
    </head>
    <body>
    <form action="/login/?from={{ from }}" method="POST">
    账号:<input type="text" value="" name="username" /><br/>
    密码:<input type="password" value="" name="passwd" /><br/>
    <input type="submit" value="登陆" />
    </form>
    </body>
    </html>
  • 过期时间

    • set_expiry(value):设置会话的过期时间
    • 如果没有指定,则默认两个星期后过期
    • 如果value是一个整数,会话会在value秒没有活动后过期
    • 如果value是timedelta对象,会话将在当前时间加上这个指定的日期/时间后过期
    • 如果value是0,那么用户会话的cookie将在用户的浏览器关闭时过期
    • 如果value是None,那么会话永不过期
      1
      2
      3
      4
      5
      6
      request.session["username"] = username
      url = "/" + url +"/"
      response = redirect(url)

      # 设置过期时间
      request.session.set_expiry(10)
  • 存储session

    • 基于数据库的会话:

      • 默认的会话存储方式
        1
        SESSION_ENGINE='django.contrib.sessions.backends.db'
    • 基于缓存的会话

      • 只存在本地内存中,如果丢失则不能找回,比数据库的方式读写更快
        1
        SESSION_ENGINE='django.contrib.sessions.backends.cache'
    • 缓存和数据库同时使用

      • 优先从本地缓存中获取,如果没有则从数据库中获取
        1
        SESSION_ENGINE='django.contrib.sessions.backends.cached_db'
  • 使用redis缓存session

    • 安装django-redis-sessionpip install django-redis-sessions
    • 配置:在settings.py最后边添加以上代码
      1
      2
      3
      4
      5
      6
      SESSION_ENGINE = 'redis_sessions.session'
      SESSION_REDIS_HOST = 'localhost'
      SESSION_REDIS_PORT = 6379
      SESSION_REDIS_DB = 0
      SESSION_REDIS_PASSWORD = ''
      SESSION_REDIS_PREFIX = 'session'