@


一个视图函数(类),简称视图,是一个简单的Python函数(类),它接受Web请求并且返回Web响应。

响应可以是一张网页的HTML内容,一个重定向,一个404错误,一个XML文档,或者一张图片。

无论视图本身包含什么逻辑,都要返回响应。代码写在哪里也无所谓,只要它在你当前项目目录下面。除此之外没有更多的要求了,可以说“没什么神奇的地方”。

为了将代码存放位置统一,大家约定成俗将视图放置在项目(project)或应用程序(app)目录中的名为views.py的文件中。

一个简单的视图:

# 以HTML文档的形式返回当前日期和时间
from django.http import HttpResponse
import datetime def current_datetime(request):
now = datetime.datetime.now()
html = '<html><body>It is now %s.</body></html>' % now
return HttpResponse(now)

让我们来逐行解释上面的代码:

  1. 首先,我们从Django.http模块中导入了HttpResponse类,以及Python的datetime库.
  2. 接着,我们定义了current_datetime函数,这个函数就称为视图函数,每个视图函数都适用HttpRequest对象作为第一个参数,并且通常称之为request.
  3. 这个视图会返回一个Httpresponse对象,其中包含生成的响应。每个视图函数都负责返回一个HttpResponse对象.

Django使用请求和响应对象通过系统传递状态.

.

当浏览器向服务器请求一个页面时,Django创建一个HttpRequest对象,该对象包含关于请求的元数据。然后,Django加载相应的视图,将这个HttpRequest对象作为第一个参数传递给视图函数.

.

每个视图负责返回一个HttpResponse对象.



FBV 与 CBV

FBV (function based view) 基于函数的视图.

CBV (class based view) 基于类的视图.

对于相同的逻辑,FBV与CBV的写法:

FBV

from django.shortcuts import render, redirect

def classes_add(request):
if request.method == 'POST':
add_classes_name = request.POST.get('add_classes_name') # 提取班级名称
Classes.objects.create(name=add_classes_name) # 将新建班级写入数据库
return redirect('/classes/') # 跳转至展示页面
return render(request, 'classes_add.html') # 返回添加页面 # urls文件
url(r'^classes_add/$', views.classes_add),

CBV

from django.shortcuts import render, redirect
from django.views import View class ClassesAdd(View):
# 可自定义允许的请求
# http_method_names = ['get', 'post'] # 处理get请求的逻辑
def get(self, request):
return render(request, 'classes_add.html') # 返回添加页面 # 处理post请求的逻辑
def post(self, request):
add_classes_name = request.POST.get('add_classes_name') # 提取班级名称
Classes.objects.create(name=add_classes_name) # 将新建班级写入数据库
return redirect('/classes/') # 跳转至展示页面 # urls文件
url(r'^classes_add/$', views.ClassesAdd.as_view()),


给视图加装饰器

FBV本身就是函数,所以和给普通函数加装饰器无差异.

使用装饰器装饰CBV

类中的方法与独立函数不完全相同,因此不能直接将函数装饰器应用于类中的方法,我们需要将其转换为方法装饰器.

Django中提供了method_decorator装饰器,用于将函数装饰器转换为方法装饰器.

装饰器函数如下:

import time

def wrapper(fn):
def inner(*args, **kwargs):
start_time = time.time()
ret = fn(*args, **kwargs)
end_time = time.time()
print("used:", end_time - start_time)
return ret
return inner

装饰CBV写法如下:

from django.shortcuts import render, redirect
from django.views import View
# 导入method_decorator
from django.utils.decorators import method_decorator class ClassesAdd(View): # 处理get请求的逻辑
@method_decorator(wrapper) #!
def get(self, request):
return render(request, 'classes_add.html') # 返回添加页面 # 处理post请求的逻辑
@method_decorator(wrapper) #!
def post(self, request):
add_classes_name = request.POST.get('add_classes_name') # 提取班级名称
Classes.objects.create(name=add_classes_name) # 将新建班级写入数据库
return redirect('/classes/') # 跳转至展示页面

关于dispatch()方法

使用CBV时需注意,请求过来后会先执行dispatch()方法,如果需要批量对具体的请求处理,如get、post等做一些操作的时,我们可以在子类中手动改写此方法,这种操作其实和在FBV上加装饰器的效果一样.

from django.shortcuts import render, redirect
from django.views import View class ClassesAdd(View): # 可自定义处理请求前后的逻辑
def dispatch(self, request, *args, **kwargs):
# 处理请求之前的逻辑
ret = super().dispatch(request, *args, **kwargs)
# 处理请求之后的逻辑
return ret # 处理get请求的逻辑
def get(self, request):
return render(request, 'classes_add.html') # 返回添加页面 # 处理post请求的逻辑
def post(self, request):
add_classes_name = request.POST.get('add_classes_name') # 提取班级名称
Classes.objects.create(name=add_classes_name) # 将新建班级写入数据库
return redirect('/classes/') # 跳转至展示页面


Request对象 与 Response对象

request对象

当一个页面被请求时,Django会创建一个包含本次请求原消息的HttpRequest对象.

Django会将这个对象自动传递给相应的视图函数,一般视图函数约定俗成使用request参数承接这个对象.

官方文档


请求相关的属性

属性 解释
path_info 返回用户访问的url,不包含域名及?后面的内容
method 请求中使用的HTTP方法的字符串表示,全大写表示
GET 包含所有HTTP GET参数的类字典对象
POST 包含所有HTTP POST参数的类字典对象
body 请求体,byte类型,request.POST的数据就是从body里面提取到的

其它属性

所有的属性都应该被认为是只读的,除非另有说明.

Django将请求报文中的请求行、头部信息、内容主题封装成HttpRequest类中的属性.

除了特殊说明的之外,其它均为只读的.

.

scheme

表示请求方案的字符串(通常为http或https)

.

body

一个字符串,代表请求报文的主体。在处理非HTTP形式的报文时非常有用,如:二进制文件、XML、Json等.

但如果要处理表单数据,还是推荐是POST.

另外,我们还可以使用Python的类文件方法去操作它,详细参考request.read()方法.

.

path

一个字符串,表示请求的路径组件(不含域名及?后面的内容).

.

encoding

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

如果为None,则表示是使用DEFAULT_CHARSET的设置,默认为"utf-8".

此属性是可写的,可以通过修改它来改变访问表单数据使用的编码,修改后对属性的任何访问都将使用新的encoding值(例如从GET或POST中读取数据).

如果确定表单数据的编码不是DEFAULT_CHARSET,则使用它.

.

POST

一个类似于字典的对象,如果请求中包含表单数据,则将这些数据封装成QueryDict对象.

POST请求可以带有空的POST字典 —— 通过HTTP POST方法发送一个没有任何数据的表单,也依然会创建QueryDict对象.

因此,我们使用if request.method == 'POST':来判断使用的是否是POST方法,而不是使用if request.method:

另外,如果使用POST上传文件的话,文件信息将包含在FILES属性中.

.

COOKIES

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

.

FILES

一个类似于字典的对象,包含所有的上传文件信息.

FILES中的每个键为< input type="file" name="" />中name,值则为对应的数据.

注意,FILES只有在请求的方法为POST且提交的< form>表单中带有enctype="multipart/form-data"的情况下才会包含数据。否则,FILES将为一个空的类似于字典的对象.

.

session

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

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

完整的细节请参见关于会话的文档.

META

一个标准的Python字典,包含所有的HTTP首部.

具体的头部信息取决于客户端和服务器.

.

CONTENT_LENGTH —— 请求的正文的长度(是一个字符串)。

CONTENT_TYPE —— 请求的正文的MIME 类型。

HTTP_ACCEPT —— 响应可接收的Content-Type。

HTTP_ACCEPT_ENCODING —— 响应可接收的编码。

HTTP_ACCEPT_LANGUAGE —— 响应可接收的语言。

HTTP_HOST —— 客服端发送的HTTP Host 头部。

HTTP_REFERER —— Referring 页面。

HTTP_USER_AGENT —— 客户端的user-agent 字符串。

QUERY_STRING —— 单个字符串形式的查询字符串(未解析过的形式)。

REMOTE_ADDR —— 客户端的IP 地址。

REMOTE_HOST —— 客户端的主机名。

REMOTE_USER —— 服务器认证后的用户。

REQUEST_METHOD —— 一个字符串,例如"GET" 或"POST"。

SERVER_NAME —— 服务器的主机名。

SERVER_PORT —— 服务器的端口(是一个字符串)。

.

从上面可以看到,除 CONTENT_LENGTH 和 CONTENT_TYPE 之外,请求中的任何 HTTP 首部转换为 META 的键时,

都会将所有字母大写并将连接符替换为下划线最后加上 HTTP_ 前缀。

所以,一个叫做 X-Bender 的头部将转换成 META 中的 HTTP_X_BENDER 键。

user

一个 AUTH_USER_MODEL 类型的对象,表示当前登陆的用户.

如果当前没有用户登陆,则user将设置为 django.contrib.auth.models.AnonymousUser 的一个实例.

可以通过 is_authenticated() 来区分它们.

例:

if request.user.is_authenticated():
# Do something for logged-in users.
else:
# Do something for anonymous users.

user 只用当Django启用 AuthenticationMiddleware 中间件时才可用.

.

匿名用户: classes models.AnonymousUser

django.contrib.auth.models.AnonymousUser 类实现了Django.contrib.auth.models.User 接口,但具有下面几个不同点:

.

id 永远为None.

username 永远为空字符串.

get_username() 永远返回空字符串.

is_staff 与 is_superuser 永远为False.

is_active 永远为 False.

groups 与 user_permissions 永远为空.

is_anonymous() 返回True 而不是False.

is_authenticated() 返回False 而不是True.

set_password()、check_password()、save()、delete() 都将引发 NotImplementedError 错误

New in Django 1.8:

新增 AnonymousUser.get_username() 以更好地模拟 django.contrib.auth.models.User。

上传文件实例:

def upload(request):
if request.method == 'POST':
file_obj = request.FILES.get('file') # 获取文件对象(获取文件信息要用FILES)
upload_file_path = os.path.join(settings.BASE_DIR, 'upload_file', file_obj.name) # 文件上传路径, file_obj.name为str类型
# 判断文件是否存在的逻辑
if os.path.exists(upload_file_path):
name, suffix = file_obj.name.split('.') # 切割文件名与文件后缀
file_name = name + "_文件副本1." + suffix # 重新拼接文件名
upload_file_path = os.path.join(settings.BASE_DIR, 'upload_file', file_name) # 文件上传路径
# 判断文件是否有副本的逻辑
if os.path.exists(upload_file_path):
file_list = os.listdir(os.path.dirname(upload_file_path))
# 获取所有副本文件
file_copy_num = []
for i in file_list:
if name not in i: continue
copy_num = i.split('.')[0][-1] # 提取副本数字
if copy_num == name[-1]: continue
file_copy_num.append(copy_num)
file_copy_max = int(max(file_copy_num)) # 提取最大的副本数字
file_name = name + "_文件副本" + str(file_copy_max + 1) + '.' + suffix
upload_file_path = os.path.join(settings.BASE_DIR, 'upload_file', file_name) # 文件上传路径
with open(upload_file_path, 'wb') as f:
[f.write(chunk) for chunk in file_obj.chunks()] # 从文件里一点一点的读数据,写到文件里
return HttpResponse("文件上传成功!") # 返回提示信息
return render(request, 'upload.html') # 返回上传页面

方法

get_host

.

根据从HTTP_X_FORWARDED_HOST(如果打开 USE_X_FORWARDED_HOST,默认为False)和 HTTP_HOST 头部信息返回请求的原始主机。

.

如果这两个头部没有提供相应的值,则使用SERVER_NAME 和SERVER_PORT,在PEP 3333 中有详细描述。

.

USE_X_FORWARDED_HOST:一个布尔值,用于指定是否优先使用 X-Forwarded-Host 首部,仅在代理设置了该首部的情况下,才可以被使用。

.

例如:127.0.0.1:8000

.

注意:当主机位于多个代理后面时,get_host() 方法将会失败。除非使用中间件重写代理的首部。

get_full_path

.

返回path,如果可以 将加上查询字符串.

例如:/list/test/?name=zyk

get_signed_cookie(key, default=RAISE_ERROR, salt='', max_age=None)

.

返回签名过的Cookie 对应的值,如果签名不再合法则返回django.core.signing.BadSignature。

.

如果提供 default 参数,将不会引发异常并返回 default 的值。

.

可选参数salt 可以用来对安全密钥强力攻击提供额外的保护。max_age 参数用于检查Cookie 对应的时间戳以确保Cookie 的时间不会超过max_age 秒。

>>> request.get_signed_cookie('name')
'Tony'
>>> request.get_signed_cookie('name', salt='name-salt')
'Tony' # 假设在设置cookie的时候使用的是相同的salt
>>> request.get_signed_cookie('non-existing-cookie')
...
KeyError: 'non-existing-cookie' # 没有相应的键时触发异常
>>> request.get_signed_cookie('non-existing-cookie', False)
False
>>> request.get_signed_cookie('cookie-that-was-tampered-with')
...
BadSignature: ...
>>> request.get_signed_cookie('name', max_age=60)
...
SignatureExpired: Signature age 1677.3839159 > 60 seconds
>>> request.get_signed_cookie('name', False, max_age=60)
False

is_secure()

.

如果请求时安全的,则返回True,即请求时通过HTTPS发起的.

is_ajax

.

如果请求是通过XMLHttpRequest 发起的,则返回True,方法是检查 HTTP_X_REQUESTED_WITH 相应的首部是否是字符串'XMLHttpRequest'。

.

大部分现代的 JavaScript 库都会发送这个头部。如果你编写自己的 XMLHttpRequest 调用(在浏览器端),你必须手工设置这个值来让 is_ajax() 可以工作。

.

如果一个响应需要根据请求是否是通过AJAX 发起的,并且你正在使用某种形式的缓存例如Django 的 cache middleware,你应该使用 vary_on_headers('HTTP_X_REQUESTED_WITH') 装饰你的视图以让响应能够正确地缓存。

注意:键值对中的值为多个时(例如checkbox类型的input标签),因该使用getlist()方法.

response对象

与Django自动创建的HttpRequest对象相比,HttpResponse对象是我们的职责范围了,我们写的每个视图都需要实例化,填充和返回一个HttpResponse.

HttpResponse类 位于django.http模块中.

传递字符串:

from django.http import HttpResponse
response = HttpResponse("Here's the text of the Web page.")
response = HttpResponse("Text only, please.", content_type="text/plain")

设置或删除响应头消息:

response = HttpResponse()
response['Content-Type'] = 'text/html; charset=UTF-8'
del response['Content-Type']

属性

  • HttpResponse.content:响应内容
  • HttpResponse.charset:响应内容的编码
  • HttpResponse.status_code:响应的状态吗


JsonResponse对象

JsonResponse是HttpResponse的子类,专门用来生成JSON编码的响应.

from django.http import JsonResponse

def test(request):
dct = {'name': 'zyk', 'sex': 'boy'}
response = JsonResponse(dct)
print(response.content)
return response

默认只会传递字典类型的数据,如果要传递非字典类型的数据,需要设置参数safe=False:

response = JsonResponse([1, 2, 3], safe=False)

【Django】视图系统的更多相关文章

  1. Django 视图系统

    Django 视图系统 概念 一个视图函数,简称视图,是一个简单的Python函数,用于接受Web请求并返回Web响应. 通常将视图函数写在project或app目录中的名为views.py文件中 简 ...

  2. python 终极篇 --- django 视图系统

    Django的View(视图) 一个视图函数(类),简称视图,是一个简单的Python 函数(类),它接受Web请求并且返回Web响应. 响应可以是一张网页的HTML内容,一个重定向,一个404错误, ...

  3. Django 视图系统(views)

    介绍 一个视图函数(类),简称视图,是一个简单的Python 函数(类),它接受Web请求并且返回Web响应. 响应可以是一张网页的HTML内容,一个重定向,一个404错误,一个XML文档,或者一张图 ...

  4. Django视图系统

    Django的view(视图)                                 一个视图函数(类),简称视图,是一个简单的Python 函数(类),它接受Web请求并且返回Web响应. ...

  5. Django框架详细介绍---视图系统

    Django视图系统 1.什么是视图 在Django中,一个视图函数/类,称为视图.实质就是一个用户自定义的简单函数,用来接收WEB请求并xing响应请求,响应的内容可以是一个HTML文件.重定向.一 ...

  6. Django框架简介-视图系统

    2.3 视图系统 一个视图函数(类),简称视图,是一个简单的Python 函数(类),它接受Web请求并且返回Web响应. 响应可以是一张网页的HTML内容,一个重定向,一个404错误,一个XML文档 ...

  7. django框架--视图系统

    目录 一.视图函数的理解 二.视图函数的定位 三.请求对象HttpRequest 四.响应对象HttpResponse 一.视图函数的理解 视图函数的作用是,对指定的url执行业务逻辑,视图函数将会作 ...

  8. Django视图层之路由配置系统(urls)

    视图层之路由配置系统(urls) URL配置(URLconf)就像Django 所支撑网站的目录.它的本质是URL与要为该URL调用的视图函数之间的映射表:你就是以这种方式告诉Django,对于这个U ...

  9. 【python】-- Django路由系统(网址关系映射)、视图、模板

    Django路由系统(网址关系映射).视图.模板 一.路由系统(网址关系映射) 1.单一路由对应: 一个url对应一个视图函数(类) urls.py: url(r'^test', views.test ...

  10. 【Mac系统 + Python + Django】之开发一个发布会系统【Django视图(二)】

    此学习资料是通过虫师的python接口自动化出的书学习而来的,在此说明一下,想学习更多的自动化的同学可以找虫师的博客园,非广告,因为我python+selenium自动化也是跟虫师学的,学习效果很好的 ...

随机推荐

  1. cocos2d_x_01_环境搭建

    终于效果图: Cocos2d-x-3.3 Mac 安装 下载地址: 參考文档:  在线API列表:  Cocos2d-x-3.3 版本号 从配置安装到创建项目都是命令行 官网下载最新版本号Cocos2 ...

  2. 想做web前端project师应该学习些什么?

    偶然间看到这篇文章.感觉博主写的挺不错的,假设你想做web前端project师的话,建议您阅读下面这篇文章,事实上web前端project师所做的工作事实上就是站点设计,有些小公司的美工事实上就是做w ...

  3. QUERY_REWRITE_ENABLED

    官方文档中: QUERY_REWRITE_ENABLED Property Description Parameter type String Syntax QUERY_REWRITE_ENABLED ...

  4. [NOIP2015模拟10.22] 最大子矩阵 解题报告(单调栈)

    Description 我们将矩阵A中位于第i行第j列的元素记作A[i,j].一个矩阵A是酷的仅当它满足下面的条件:       A[1,1]+A[r,s]<=A[1,s]+A[r,1](r,s ...

  5. kindeditor 不能编辑 问题

    /*显示上传窗体*/ function ShowUplodToDaily() { var _sdata = grid.getSelecteds(); if (_sdata) { /*创建编辑器*/ v ...

  6. Spring项目的配置文件们(web.xml context servlet springmvc)

    我们的spring项目目前用到的配置文件包括1--web.xml文件,这是java的web项目的配置文件.我理解它是servlet的配置文件,也就是说,与spring无关.即使你开发的是一个纯粹jsp ...

  7. IBM主机上清除告警黄灯方法

    机器亮黄灯告警一般是有硬件问题(单电源等可能有安全隐患的硬件配置也可能造成黄灯亮起),见到后首先进行下硬件诊断,方法如下: 诊断系统,判断是否硬件故障:1.Root用户执行diag: 2.回车后,进第 ...

  8. CF85E Guard Towers(二分答案+二分图)

    题意 已知 N 座塔的坐标,N≤5000 把它们分成两组,使得同组内的两座塔的曼哈顿距离最大值最小 在此前提下求出有多少种分组方案 mod 109+7 题解 二分答案 mid 曼哈顿距离 >mi ...

  9. (转载)详细图解mongodb下载、安装、配置与使用

    记得在管理员模式下运行CMD,否则服务将启动失败 转载:http://blog.csdn.net/boby16/article/details/51221474 详细图解,记录 win7 64 安装m ...

  10. Linux LVM在线扩容

    环境: 虚拟化环境,SUSE Linux Enterprise Server 11sp3,直接把虚拟磁盘从100G改成150G. 现有的LVM是100G,/home 的LV需要再加50G. 步骤: f ...