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'