Django 视图
Django 视图
一个视图函数(类),简称视图,是一个简单的Python 函数(类),它接受Web请求并且返回Web响应。
响应可以是一张网页的HTML内容,一个重定向,一个404错误,一个XML文档,或者一张图片。
无论视图本身包含什么逻辑,都要返回响应。代码写在哪里也无所谓,只要它在你当前项目目录下面。除此之外没有更多的要求了——可以说“没有什么神奇的地方”。为了将代码放在某处,大家约定成俗将视图放置在项目(project)或应用程序(app)目录中的名为views.py的文件中。
Django使用请求和响应对象来通过系统传递状态。
当浏览器向服务端请求一个页面时,Django创建一个HttpRequest对象,该对象包含关于请求的元数据。然后,Django加载相应的视图,将这个HttpRequest对象作为第一个参数传递给视图函数。
每个视图负责返回一个HttpResponse对象。
CBV和FBV
基于类的的View,叫CBV(function based view )
基于函数的的View,叫FBV(class based view)
FBV
# 增加出版社
def add_publisher(request):
# 定义变量
new_publisher, err_msg = '', ''
# 判断请求
if request.method == 'POST':
new_publisher = request.POST.get('new_publisher').strip()
# 判断出版社名称是否为空
if not new_publisher:
err_msg = '不能为空'
# 判断出版社是否已存在
elif models.Publisher.objects.filter(name=new_publisher):
err_msg = '出版社已存在'
else:
models.Publisher.objects.create(name=new_publisher)
return redirect('/publisher_list/')
return render(request, 'add_publisher.html', {'new_publisher': new_publisher, 'err_msg': err_msg})
CBV
- 定义
# CBV版 add_publisher
# 增加出版社
from django.views import View
class AddPublisher(View):
def get(self, request):
return render(request, 'add_publisher.html')
def post(self, request):
new_publisher = request.POST.get('new_publisher').strip()
# 判断出版社名称是否为空
if not new_publisher:
err_msg = '不能为空'
# 判断出版社是否已存在
elif models.Publisher.objects.filter(name=new_publisher):
err_msg = '出版社已存在'
else:
models.Publisher.objects.create(name=new_publisher)
return redirect('/publisher_list/')
return render(request, 'add_publisher.html', {'new_publisher': new_publisher, 'err_msg': err_msg})
- 使用
url(r'^add_publisher/', views.AddPublisher.as_view()),
-
CBV的流程
-
views.AddPublisher.as_view() 程序加载的时候执行 ——》 view函数
-
当请求到来的时候执行view函数:
- self = AddPublisher()
- self.request = request
- 执行self.dispatch方法
- 判断请求方式是否被允许
- 允许时,通过反射获取到AddPublisher中定义的get或者post方法 ——》handler
- 不允许时,self.http_method_not_allowed ——》handler
- 执行handler 拿到返回结果 Httpresponse对象
- 判断请求方式是否被允许
-
-
给CBV加装饰器
from django.utils.decorators import method_decorator
-
加载某个get/post的方法上:
@method_decorator(timer) def get(self, request): pass
-
加在self.dispatch方法上:
@method_decorator(timer) def dispatch(self, request, *args, **kwargs): pass
-
加在类上:
@method_decorator(timer, name='post') @method_decorator(timer, name='get') class AddPublisher(View): pass
-
-
区别
- 不使用method_decorator
func: <function AddPublisher.dispatch at 0x00000163735176A8>
args :<app01.views.AddPublisher object at 0x00000163735F7EF0> <WSGIRequest: GET '/add_publisher/'>- 使用method_decorator
func:<function method_decorator.
._dec. ._wrapper. .bound_func at 0x0000019664B4A378>
arsgs: <WSGIRequest: GET '/add_publisher/'>- 在普通装饰器中加
def inner(request,*args, **kwargs):
,即可起到相同效果
Request对象和Response对象
request对象
当一个页面被请求时,Django就会创建一个包含本次请求原信息的HttpRequest对象。
Django会将这个对象自动传递给响应的视图函数,一般视图函数约定俗成地使用 request 参数承接这个对象。
请求相关的常用值
- path_info 返回用户访问url,不包括域名
- method 请求中使用的HTTP方法的字符串表示,全大写表示。
- GET 包含所有HTTP GET参数的类字典对象
- POST 包含所有HTTP POST参数的类字典对象
- body 请求体,byte类型 request.POST的数据就是从body里面提取到的
- path_info 路径信息
- get_full_path() 路径信息 + 参数
- get_host() 获取主机
- META 一个标准的Python 字典,包含所有的HTTP 首部。具体的头部信息取决于客户端和服务器
- FILES 一个类似于字典的对象,包含所有的上传文件信息。
上传文件注意事项:
- form表单的enctype = 'multipart/form-data'
- request.FILES中获取文件对象
- 使用文件对象的chunks()
代码实例
def upload(request):
'''
保存上传文件前,数据需要存放在某个位置。默认当上传文件小于2.5M时,django会将上传文件的全部内容读进内存。从内存读取一次,写磁盘一次。
但当上传文件很大时,django会把上传文件写到临时文件中,然后存放到系统临时文件夹中。
:param request:
:return:
'''
if request.method == 'POST':
# 从请求的FILES中获取上传文件的文件名,file为页面上type=files类型input的name属性值
file_name = request.FILES['file_name'].name
with open(file_name, 'wb') as f:
# 从上传的文件对象中一点一点读
for chunk in request.FILES['file_name'].chunks():
f.write(chunk)
# 写入本地文件
return HttpResponse('上传成功!')
return render(request, 'upload.html')
Response对象
我们写的每个视图都需要实例化,填充和返回一个HttpResponse。
HttpResponse类位于django.http模块中。
HttpResponse
传递字符串
from django.http import HttpResponse
response = HttpResponse("Here's the text of the Web page.")
设置或删除响应头信息
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
from django.shortcuts import HttpResponse
def json_test(rerquest):
data = {'name': 'root', 'pwd': '123'}
ret = JsonResponse(data) # <JsonResponse status_code=200, "application/json">
ret2 = HttpResponse(data) # <HttpResponse status_code=200, "text/html; charset=utf-8">
ret3 = HttpResponse(data, content_type='application/json') # <HttpResponse status_code=200, "application/json">
return ret
Django shortcut functions
render()
结合一个给定的模板和一个给定的上下文字典,并返回一个渲染后的 HttpResponse 对象。
参数:
- request: 用于生成响应的请求对象。
- template_name:要使用的模板的完整名称,可选的参数
- context:添加到模板上下文的一个字典。默认是一个空字典。如果字典中的某个值是可调用的,视图将在渲染模板之前调用它。
- content_type:生成的文档要使用的MIME类型。默认为 DEFAULT_CONTENT_TYPE 设置的值。默认为'text/html'
- status:响应的状态码。默认为200。
- useing: 用于加载模板的模板引擎的名称。
redirect()
参数可以是:
- 一个模型:将调用模型的get_absolute_url() 函数
- 一个视图,可以带有参数:将使用urlresolvers.reverse 来反向解析名称
- 一个绝对的或相对的URL,将原封不动的作为重定向的位置。
默认返回一个临时的重定向;传递permanent=True 可以返回一个永久的重定向。