写点什么

Django 之视图篇

用户头像
若尘
关注
发布于: 2021 年 05 月 27 日
Django 之视图篇

views 视图

视图概述

  • 视图即视图函数,接收 web 请求并返回 web 响应的事务处理函数

  • 响应指符合 http 协议要求的任何内容,包括 json,string,html 等

  • 本章忽略事务处理,重点在如何处理返回结果上

其他简单视图

  • django.http 给我们提供了很多和 HttpResponse 类似的简单视图,通过查看 django.http 代码我们知道

  • 此类视图使用方法基本类似,可以通过 return 语句作为直接反馈返回给浏览器

  • Http404 为 Exception 子类,所以需要 raise 使用

HttpResponse 详解

  • 方法

  • init: 使用网页内容实例化 HttpResponse 对象

  • write(content): 以文件的方式写

  • flush(): 以文件的方式输出缓存区

  • set_cookie(key, value='', max_age=None, expires=None): 设置 cookie

  • key, value 都是字符串类型

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

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

  • max_age 与 expires 二选一

  • 如果不指定过期时间,则两个星期后过期

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

HttpResponseRedirect

  • 重定向,服务器跳转

  • 构造函数的第一个参数用来指定重定向的地址

Request 对象

  • Request 介绍

  • 服务器接收到 http 协议的请求后,会根据报文创建 HttpResponse 对象

  • 视图函数的第一个参数是 HttpResponse 对象

  • 在 django.http 模块中定义了 HttpResponse 对象的 API

  • 属性

  • 下面除非特别说明,属性都是只读的

  • path: 一个字符串,表示请求的页面的完整路径,不包含域名

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

  • encoding: 一个字符串,表示提交的数据的编码方式

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

  • 这个属性是可写的,可以通过修改它来修改访问表单数据使用

  • GET: 一个类似于字典的对象,包含 get 请求方式的所有参数

  • POST: 一个类似于字典的对象,包含 post 请求方式的所有参数

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

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

  • session: 一个即可读又可写的类似于字典的对象,表示当前的会话,

  • 只有当 Django 启用会话的支持时才可用

  • 详细内容见"状态保持"

  • 方法

  • is_ajax(): 如果请求是通过 XMLHttpResponse 发起的,则返回 True

QueryDict 对象

  • 定义在 django.http.QueryDict

  • request 对象的属性 GET、POST 都是 QueryDict 类型的对象

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

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

  • 只能获取键的一个值

  • 如果一个键同时拥有多个值,获取最后一个值

  • 方法 getlist(): 根据键获取值

  • 将键的值以列表返回,可以获取一个键的多个值

GET 属性

  • QueryDict 类型的对象

  • 包含 get 请求方式的所有参数

  • 与 url 请求地址中的参数对应,位于?后面

  • 参数的格式是键值对,即 key1 = value1

  • 多个参数之间,使用 &相连,如 key1=value1&key2=value2

  • 键是开发人员定下来的,值是可变的

  • 案例/views/v12_get


def v12_get(request):    rst = ""    for k,v in request.GET.items():        rst += k + '-->' + v        rst += ','
return HttpResponse("Get value of Request is {0}".format(rst))
复制代码

POST 属性

  • QueryDict 类型的对象

  • 包含 post 请求方式的所有参数

  • 与 form 表单中的控件对应

  • 表单中控件必须有 name 属性, name 为键, value 为值

  • checkbbox 存在一键多值的问题

  • 键是开发人员定下来的,值是可变的

  • 案例/views/v9_post

  • settint 中设置模板位置

  • 设置 get 页面的 urls 和函数


  def v9_post(request):      rst = ''      for k, v in request.POST.items():          rst += k + '->' + v          rst += ','      return HttpResponse("Get value of POST is {0}".format(rst))
复制代码

手动编写视图

  • 实验目的

  • 利用 django 快捷函数手动编写视图处理函数

  • 编写过程中理解视图运行原理

  • 分析

  • django 把所有请求信息封装入 request

  • django 通过 urls 模块把相应请求跟事件处理函数连接起来,并把 request 作为参数传入

  • 在相应的处理函数中,我们需要完成两部分

  • 处理业务

  • 把结果封装并返回,我们可以使用 HttpResponse,同样也可以自己处理此功能

  • 本案例不介绍业务处理,把目光集中在如何渲染结果并返回

  • render(request, template_name[, context][, context_instance][, content_type][, status][, current_app][, dirs][, using])

  • 使用模板和一个给定的上下文环境,返回一个渲染和的 HttpResponse 对象

  • request: django 的传入请求

  • template_name: 模板名称

  • content_instance: 上下文环境

  • 案例参看代码 ruochen_views/teacher_app/views/render_test


  def rander_test(request):      # 环境变量      # c = dict()      rsp = render(request, "render.html")      # rsp = HttpResponse(request, "render.html")      return rsp
复制代码


  • render_to_response

  • 根据给定的上下文字典渲染给定模板,返回渲染后的 HttpResponse

  • 系统内建视图

  • 系统内建视图,可以直接使用

  • 404

  • default.page_not_found(request, template_name='404.html')

  • 系统引发 Http404 时触发

  • 默认传递 request_path 变量给模板,即导致错误的 URL

  • DEBUG=True 则不会调用 404, 取而代之是调试信息

  • 404 视图会被传递一个 RequestContext 对象并且可以访问模板上下文处理器提供的变量(MEDIA_URL 等)

  • 500(server error)

  • defaults.server_error(request, template_name='500.html')

  • 需要 DEBUG=False,否则不调用

  • 403 (HTTP Forbidden) 视图

  • defaults.permission_denied(request, template_name='403.html')

  • 通过 PermissionDenied 触发

  • 400 (bad request) 视图

  • defaults.bad_request(request, template_name='400.html')

  • DEBUG=False

基于类的视图

简单说一下基于类的视图


  • 和基于函数的视图的优势和区别:

  • HTTP 方法的 methode 可以有各自的方法,不需要使用条件分支来解决

  • 可以使用 OOP 技术(例如 Mixin)

  • 概述

  • 核心是允许使用不同的实例方法来相应不同的 HTTP 请求方法,而避开条件分支实现

  • as_view 函数昨晚类的可调用入库,该方法创建一个实例并调用 dispatch 方法,按照请求方法对请求进行分发,如果该方法没有定义,则引发 HttpResponseNotAllowed

  • 类属性使用

  • 在类定义时直接覆盖

  • 在调用 as_view 的时候直接昨晚参数使用,例如:


        urlpatterns = [            url(r'^about/', GreetingView.as_view(greeting="G'day")),            ]
复制代码


  • 对基于类的视图的扩充大致有三种方法: Mixin, 装饰 as_view, 装饰 dispatch

  • 使用 Mixin

  • 多继承的一种形式,来自弗雷的行为和属性组合在一起

  • 解决多继承问题

  • View 的子类只能单继承,多继承会导致不可期问题

  • 多继承带来的问题:

  • 结构复杂

  • 优先顺序模糊

  • 功能冲突

  • 解决方法

  • 规格继承 - java interface

  • 实现继承 - python,ruby

  • 在 URLconf 中装饰


    from django.contrib.auth.decorators import login_required, permission_required    from django.views.generic import TemplateView
from .views import VoteView
urlpatterns = [ url(r'^about/', login_required(TemplateView.as_view(template_name="secret.html"))), url(r'^vote/', permission_required('polls.can_vote')(VoteView.as_view())), ]
复制代码


  • 装饰类

  • 类的方法和独立方法不同,不能直接运用装饰器,需要用 methode_decorator 进行装饰


        from django.contrib.auth.decorators import login_required        from django.utils.decorators import method_decorator        from django.views.generic import TemplateView
class ProtectedView(TemplateView): template_name = 'secret.html'
@method_decorator(login_required) def dispatch(self, *args, **kwargs): return super(ProtectedView, self).dispatch(*args, **kwargs)
复制代码

相关代码

视图篇用到的相关代码如下


  • urls.py


from django.conf.urls import include, urlfrom django.contrib import admin
from teacher_app import views as v
urlpatterns = [ # Examples: # url(r'^$', 'ruochen_views.views.home', name='home'), # url(r'^blog/', include('blog.urls')),
url(r'^admin/', include(admin.site.urls)),
url(r'^teacher/', v.teacher), url(r'^v2_exp/', v.v2_exception),
url(r'^v10_1/', v.v10_1), url(r'^v10_2/', v.v10_2), url(r'^v11_hello/', v.v11, name='v11'),
url(r'^v12/', v.v12_get), url(r'^v9_get/', v.v9_get), url(r'^v9_post/', v.v9_post),
url(r'render_test/', v.rander_test), url(r'render2_test/', v.rander2_test), url(r'render3_test/', v.rander3_test),
url(r'render1_to_res/', v.render4_test),
url(r'^get404/', v.get404),]
复制代码


  • views.py


from django.shortcuts import render, render_to_responsefrom django.http import HttpResponse, Http404, HttpResponseRedirectfrom django.core.urlresolvers import reverse# Create your views here.
def teacher(r): return HttpResponse('这是teacher的一个视图')
def v2_exception(r): raise Http404 return HttpResponse('OK')
def v10_1(r): return HttpResponseRedirect(reverse('v11'))
def v10_2(r): return HttpResponseRedirect(reverse('v11'))
def v11(r): return HttpResponse('v11 访问返回')
def v12_get(request): rst = "" for k,v in request.GET.items(): rst += k + '-->' + v rst += ','
return HttpResponse("Get value of Request is {0}".format(rst))
def v9_get(request): # 渲染一个模板并返回 return render_to_response('for_post.html')
def v9_post(request): rst = '' for k, v in request.POST.items(): rst += k + '->' + v rst += ',' return HttpResponse("Get value of POST is {0}".format(rst))
def rander_test(request): # 环境变量 # c = dict() rsp = render(request, "render.html") # rsp = HttpResponse(request, "render.html") return rsp
def rander2_test(request): # 环境变量 c = dict()
c['name'] = "ruochen" c['name2'] = "ruochen2" c['name3'] = "ruochen3"
rsp = render(request, "render2.html", context=c) return rsp
def rander3_test(request):
from django.template import loader
# 得到模板 t = loader.get_template('render2.html') print(type(t))
r = t.render({"name": "ruochen"}) print(type(r)) return HttpResponse(r)
def render4_test(request): # 反馈回m模板render2.html rsp = render_to_response("render2.html", context={"name": "ruochen"}) return rsp
def get404(request): from django.views import defaults return defaults.page_not_found(request, template_name="render.html")
复制代码


  • templates

  • for_post.html


  <html>  <head>      <title>Title</title>  </head>  <body>  <form method="post" action="/v9_post/">      姓名: <input type="text" name="uname"/><br>      密码: <input type="password" name="upwd"/><br>      性别: <input type="radio" name="ugender" value="1"/>男      <input type="radio" name="ugender" value="0"/>女<br>      爱好: <input type="checkbox" name="uhobby" value="恰饭"/>恰饭      <input type="checkbox" name="uhobby" value="跳楼"/>跳楼      <input type="checkbox" name="uhobby" value="喝酒"/>喝酒      <input type="checkbox" name="uhobby" value="跳楼"/>爬山<br>      <input type="submit" value="提交"/>  </form>  </body>  </html>
复制代码


- render.html
复制代码


  <!DOCTYPE html>  <html lang="en">  <head>      <meta charset="UTF-8">      <title>Title</title>  </head>  <body>    <h1>Render example by ruochen</h1>    </body>  </html>
复制代码


- render2.html
复制代码


  <!DOCTYPE html>  <html lang="en">  <head>      <meta charset="UTF-8">      <title>Title</title>  </head>  <body>    <h1>WebPage for rander with {{name}}</h1>    </body>  </html>
复制代码


  • settings.py


"""Django settings for ruochen_views project.
Generated by 'django-admin startproject' using Django 1.8.
For more information on this file, seehttps://docs.djangoproject.com/en/1.8/topics/settings/
For the full list of settings and their values, seehttps://docs.djangoproject.com/en/1.8/ref/settings/"""
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)import os
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

# Quick-start development settings - unsuitable for production# See https://docs.djangoproject.com/en/1.8/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!SECRET_KEY = 'a^-vz9v!e2ks%m=d*&fu$r)qc42vpgkqny9jl36plg$(3jtp#q'
# SECURITY WARNING: don't run with debug turned on in production!DEBUG = True
ALLOWED_HOSTS = ["*"]

# Application definition
INSTALLED_APPS = ( 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'teacher_app',)
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',)
ROOT_URLCONF = 'ruochen_views.urls'
TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [os.path.join(BASE_DIR, "templates")], 'APP_DIRS': True, 'OPTIONS': { 'context_processors': [ 'django.template.context_processors.debug', 'django.template.context_processors.request', 'django.contrib.auth.context_processors.auth', 'django.contrib.messages.context_processors.messages', ], }, },]
WSGI_APPLICATION = 'ruochen_views.wsgi.application'

# Database# https://docs.djangoproject.com/en/1.8/ref/settings/#databases
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.sqlite3', 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), }}

# Internationalization# https://docs.djangoproject.com/en/1.8/topics/i18n/
LANGUAGE_CODE = 'en-us'
TIME_ZONE = 'UTC'
USE_I18N = True
USE_L10N = True
USE_TZ = True

# Static files (CSS, JavaScript, Images)# https://docs.djangoproject.com/en/1.8/howto/static-files/
STATIC_URL = '/static/'
复制代码


发布于: 2021 年 05 月 27 日阅读数: 14
用户头像

若尘

关注

还未添加个人签名 2021.01.11 加入

还未添加个人简介

评论

发布
暂无评论
Django 之视图篇