# 视图概述
- 视图即视图模块,接收web请求并返回web响应的事物处理模块
- 响应指符合http协议要求的任何内容,包括json,string, html等
- 是django后台的核心内容,一般在每个APP下的views.py文件里面,如果特别复杂可以有别的python文件
- 视图可以看作一个接受HttpRequest的实例,返回一个Response的类的实例的类或者函数,形如:
def views_func(request):
... ...
return HttpResponse(...)
- 相应的urls中对应的代码应该是:
... ...
path("tulingxueyuan/", views.views_func)
... ...
## 简单视图
- 目的:
- 创建一个简单视图函数
- 返回一段html代码
- 利用django.http包中的HttpResponse类
- 分析:
- HttpResponse是一个由django提供的视图类,可以用来返回简单视图
- HttpRequest尽可能不让程序员改动内容,HttpResponse则需要手动改动内容
- 为了代码简洁,从新创建v3_views项目,添加tuling应用
- 操作步骤:
1. 启动虚拟环境
> source activate tuling_django
2. 创建项目和app
>django-admin startproject v3_views
>cd v3_views
>python manage.py startapp tuling
3. 修改配置文件v3/settings.py
每从创建一个APP都应该在settings.py下添加这个APP,否则可能会导致各种问题,简单应用
也可能不影响使用。
- 添加app,修改完后代码如下:
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'tuling', #添加的新的APP
]
4. 配置pycharm让软件能直接运行manage.py函数, 具体配置参看第一张django概述
5. 运行 east/manage.py ,显示如下内容说明成功运行:
6. 浏览器中输入 http://127.0.0.1:8000/, 确认链接成功
7. 在 v3/urls.py 中添加url信息,代码如下:
from django.urls import path, include #导入include
urlpatterns = [
path('admin/', admin.site.urls),
# 新添加内容
path('tuling/', include('tuling.urls')),
]
8. 拷贝v3_views/urls.py到tuling文件夹下, tuling/urls.py 添加处理代码,代码如下:
from django.contrib import admin
from django.urls import path
from . import views #导入视图
urlpatterns = [
path('t1/', views.t1),
]
9. 在 tuling/views 添加处理代码,代码如下:
```
from django.shortcuts import render
# 导入HttpResponse作为基本视图使用
from django.http import HttpResponse
import datetime
# Create your views here.
def v1(request):
# 得到系统当前事件
now = datetime.datetime.now()
# HttpResponse允许html代码作为返回值,
html = "
It is time {0}
".format(now)
# 返回HttpResponse视图
return HttpResponse(html)
```
9. 运行以上代码并输入相应地址(http://127.0.0.1:8000/tuling/t1/)进行检查
10. 简单视图创建完毕,需要正确理解HttpResponse视图类和访问流程
- 数据流程
整个过程数据流程图大致如下:
浏览器->django:v1/urls->tuling/urls->view.t1->HttpResponse->浏览器
## 其他简单视图
- django.http给我们提供类很多和HttpResponse类似的简单视图,通过查看django.http代码我们知道,
总共django给我们定义了一下一些简单类,如下图所示:

- 此类视图使用方法基本类似,可以通过return语句作为反馈直接反馈返回给浏览器
- Http404为Exception子类,所以需要raise使用,代码案例如下
# tuling/urls.py
urlpatterns = [
path('t1/', views.t1),
path('t2/', views.t2), #引发异常
]
# tuling/views.py
.......
from django.http import Http404
.......
def t2(r):
"""
:param r: HttpRequest实例
:return:
"""
raise Http404("这个锅我不背,不背不背就不背")
最终结果如下图所示:

## HttpRequest对象
- HttpRequest介绍
- 服务器接收到http协议的请求后,会根据报文创建HttpRequest对象
- 视图函数的第一个参数是HttpRequest对象
- 在django.http模块中定义了HttpRequest对象的API
- 属性
- 下面除非特别说明,属性都是只读的
- path:一个字符串,表示请求的页面的完整路径,不包含域名
#加入请求的是以下博客地址
http://www.mycode.wang/blog/liudana/124.html
#则解析得到的request.path是:
blog/liudana/124.html
- method:一个字符串,表示请求使用的HTTP方法,常用值包括:'GET'、'POST', 具体讲解会在Restfull中
- encoding:一个字符串,表示提交的数据的编码方式
- 如果为None则表示使用浏览器的默认设置,一般为utf-8
- 这个属性是可写的,可以通过修改它来修改访问表单数据使用的编码,接下来对属性的任何访问将使用新的encoding值
- GET:一个类似于字典的对象,包含get请求方式的所有参数
- POST:一个类似于字典的对象,包含post请求方式的所有参数
- FILES:一个类似于字典的对象,包含所有的上传文件
- COOKIES:一个标准的Python字典,包含所有的cookie,键和值都为字符串
- session:一个既可读又可写的类似于字典的对象,表示当前的会话,只有当Django 启用会话的支持时才可用,详细内容见“状态保持”
- 方法
- is_ajax():如果请求是通过XMLHttpRequest发起的,则返回True
- QueryDict对象
- 定义在django.http.QueryDict
- request对象的属性GET、POST都是QueryDict类型的对象
- 与python字典不同,QueryDict类型的对象用来处理同一个键带有多个值的情况
- 方法get():根据键获取值
- 只能获取键的一个值
- 如果一个键同时拥有多个值,获取最后一个值
- 方法getlist():根据键获取值
- 将键的值以列表返回,可以获取一个键的多个值
- GET属性
- 当用户发起一个http协议中的get方法请求的时候,HttpRequest.GET会被各种值填充
- 本质上是一个QueryDict类型的对象
- 它包含get请求方式的所有参数
- 一个常见的GET请求URL形如:
HTTP:GET : http://127.0.0.1:8080/a/b/c?id=1&k=w
- 请求参数是与url请求地址中的参数对应,位于?后面的形如`k=w`的键值对
- 参数的格式是键值对,如key1=value1
- 多个参数之间,使用&连接,如key1=value1&key2=value2
- 键是开发人员定下来的,值是可变的
- 案例代码tuling/views/t3_get
# tuling/urls.py
... ...
path('t3/', views.t3_get),
... ...
# tuling/v3_views.py下代码
... ...
def t3_get(request):
rst = ""
for k,v in request.GET.items():
rst += k + "-->" + v
rst += ","
return HttpResponse("Get value of Request is {0} ".format(rst))
- 访问结果如图如图:

- 对于request.GET内容的使用,一定不能按正常字典的使用那样获取值,而应该使用
自带的get函数,确保不会出现问题,代码示例如下:
#不应该这样使用,GET是一个特殊的字典
s = r.GET["name"]
#获取GET内值的方法应该是使用内置get方法
r.GET.get("name", """)
- POST属性
- QueryDict类型的对象
- 包含post请求方式的所有参数
- 与form表单中的控件对应
- 表单中空间必须有name属性,name为键,value为值
- checkbox存在一键多值的问题
- 键是开发人员定下来的,值是可变的
- 案例 tuling/views/t4_post 和 tuling/views/t4_get
- 因为需要用到模板,需要先设置下,后面会具体讲,settings中设置模板位置
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
#添加模板位置
'DIRS': [os.path.join(BASE_DIR, 'templates')],
... ...
- 设置get页面的urls和函数
# tuling/urls.py
urlpatterns = [
... ...
#添加两个路由
path('t4_get/', views.t4_get),
path('t4_post/', views.t4_post),
]
- views中设置代码
# tuling/views.py
# 在文件中添加下面两个处理函数
def t4_get(r):
return render_to_response("for_post.html")
def t4_post(r):
rst = ""
for k,v in request.POST.items():
rst += k + "-->" + v
rst += ","
return HttpResponse("Get value of POST is {0} ".format(rst))
- 添加文件和文件夹: /tuling/templates/for_post.html
- 由于安全原因,需要在设置中安全选项中删除csrf设置
# settings.py
MIDDLEWARE = [
... ...
'django.middleware.common.CommonMiddleware',
# 下面这句话被注释掉
#'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
... ...1`
## HttpResponse详解
- 方法
- init :使用页内容实例化HttpResponse对象
- write(content):以文件的方式写
- flush():以文件的方式输出缓存区
- set_cookie(key, value='', max_age=None, expires=None):设置Cookie
- key,value都是字符串类型
- max_age是一个整数,表示在指定秒数后过期
- expires是一个datetime或timedelta对象,会话将在这个指定的日期/时间过期,注意datetime和timedelta值只有在使用PickleSerializer时才可序列化
- max_age与expires二选一
- 如果不指定过期时间,则两个星期后过期
- delete_cookie(key):删除指定的key的Cookie,如果key不存在则什么也不发生
## 4. HttpResponseRedirect
- 重定向,服务器端跳转
- 构造函数的第一个参数用来指定重定向的地址
- 案例 tuling/views.py
# 在 tuling/urls中添加一下内容
urlpatterns = [
path('t1/', views.t1),
path('t2/', views.t2),
path('t3/', views.t3_get),
path('t4_get/', views.t4_get),
path('t4_post/', views.t4_post),
path('t5_1/', views.t5_1),
path('t5_2/', views.t5_2),
path('t6/', views.t6, name="t6"),
# tuling/views.py中添加以下内容
# 导入下面内容
from django.http import HttpResponse, Http404, HttpResponseRedirect
from django.urls import reverse
... ...
def t5_1(request):
return HttpResponseRedirect("/tuling/t6")
def t5_2(request):
return HttpResponseRedirect(reverse("t6"))
def t6(request):
return HttpResponse("哈哈,这是t5的访问返回呀")
## 手动编写视图
- 实验目的:
- 利用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: 上下文环境
- render_to_response(template_name[, context][, context_instance][, content_type][, status][, dirs][, using])[source]
- 根据给定的上下文字典渲染给定模板,返回渲染后的HttpResponse
- 已经不推荐
- redirect(to, [permanent=False, ]*args, **kwargs)[source]¶
- 参数可以是:
1. 使用django.url.reverse的反向解析
2. 绝对或者相对URL,将原封不动的作为重定向的位置
- 默认返回一个临时的重定向, permanent=True时可以返回一个永久重定向
```
所谓重定向就是将网页自动转向重定向,即:301永久性重定向和302临时性重定向。
```
## 系统内建视图
- 常用视图系统有内建,可以直接使用
- 在http.views.defaults中定义
- 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
- 示例代码
# tuling/views.py
# urls也需要进行设定
from django.views import defaults
... ...
def t7(r):
return defaults.page_not_found(r, "找不到呀", "404.html")
## 基于类的视图
到现在为止我们的视图都是一个一个函数,一般每个请求对应一个函数,本章开始学习利用面向对象来
编写视图。
- 和基于函数的视图的优势和区别:
- HTTP方法的methode可以有各自的方法,不需要使用条件分支来解决
- 可以使用OOP技术(例如Mixin)
- 概述
- 核心是允许使用不同的实例方法来响应不同的HTTP请求方法,而避开条件分支实现
- as_view函数作为类的可调用入口,该方法创建一个实例并调用dispatch方法,
按照请求方法对请求进行分发,如果该
方法没有定义,则引发HttpResponseNotAllowed
- 参看案例1:
- 修改tuling/urls.py
path('t8/', views.TestView.as_view()),
- 修改tuling/views.py
from django.views.generic import View, TemplateView
class TestView(View):
def get(self, r):
return HttpResponse("Hello GET")
def post(self, r):
return HttpResponse("Hello POST")
- 类属性使用
每个类都可能有相应的类属性,我们基于类的视图一般都是作为视图类的子类存在,不可避免的需要一些
类的属性,此时一般类的属性的处理有两种方法:
- 在类定义时直接覆盖
- 在调用as_view的时候直接昨晚参数使用
- TemplateView案例
- 修改tuling/urls.py
path('t9/', views.GreetingView.as_view()),
- 修改tuling/views.py
class GreetingView(TemplateView):
#本类需要继承模板视图,默认有一个模板支持
template_name = "for_class_view.html"
#getting 在urls里面给了一个赋值
#调用post的时候明显看到getting的值发生了改变
greeting = "Say something"
def post(self, r):
data = dict(r.POST)
print(data)
print(self.greeting)
return HttpResponse("Hello ")
- 对基于类的视图的扩充大致有三种方法:
- Mixin
- 装饰as_view
- 装饰dispatch
- 使用Mixin
- 多继承的一种形式,来自父类的行为和属性组合在一起
- 解决了多继承问题
- View的子类只能单继承,多继承会导致不可期问题
- 在urls中装饰as_view
```
# 此代码是django2.0 以前代码,不保证在django2上能继续运行
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())),
]
```
- 装饰类的dispatch函数
- 类的方法和独立方法不同,不能直接运用装饰器,需要用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)
```