django之视图view
一个视图函数(类),简称视图,是一个简单的Python 函数(类),它接受Web请求并且返回Web响应。
响应可以是一张网页的HTML内容,一个重定向,一个404错误,一个XML文档,或者一张图片。
无论视图本身包含什么逻辑,都要返回响应。
CBV和FBV
FBV function based view
CBV class based view
# FBV版添加班级
def add_class(request):
if request.method == "POST":
class_name = request.POST.get("class_name")
models.Classes.objects.create(name=class_name)
return redirect("/class_list/")
return render(request, "add_class.html")
# CBV版添加班级
from django.views import View
class AddClass(View):
def get(self, request):
return render(request, "add_class.html")
def post(self, request):
class_name = request.POST.get("class_name")
models.Classes.objects.create(name=class_name)
return redirect("/class_list/")
注意:
使用CBV时,urls.py中也做对应的修改:
# urls.py中
url(r'^add_class/$', views.AddClass.as_view()),
as_view源码流程
1.项目启动 加载ur.py时,执行类.as_view() ——》 view函数
2.请求到来的时候执行view函数:
-
实例化类 ——》 self
self.request = request
-
执行seld.dispatch(request, *args, **kwargs)
-
判断请求方式是否被允许:
-
允许 通过反射获取到对应请求方式的方法 ——》 handler(get,post...)
-
不允许 self.http_method_not_allowed ——》handler
-
执行handler(request,*args,**kwargs)
返回响应 —— 》 浏览器
-
给视图加装饰器
FBV 加装饰器和普通函数一样,这里不再讲述。
def timer(func):
def inner(*args, **kwargs):
start = time.time()
ret = func(*args, **kwargs)
print("函数执行的时间是{}".format(time.time() - start))
return ret
return inner
CBV
from django.utils.decorators import method_decorator
1.加在方法上
@method_decorator(timer)
def get(self, request, *args, **kwargs):
"""处理get请求"""
2.加在dispatch方法上
使用CBV时要注意,请求过来后会先执行dispatch()这个方法,如果需要批量对具体的请求处理方法,如get,post等做一些操作的时候,
这里我们可以手动改写dispatch方法,这个dispatch方法就和在FBV上加装饰器的效果一样。
@method_decorator(timer)
def dispatch(self, request, *args, **kwargs):
# print('before')
ret = super().dispatch(request, *args, **kwargs)
# print('after')
return ret
@method_decorator(timer,name='dispatch')
class AddPublisher(View):
3.加在类上
@method_decorator(timer,name='post')
@method_decorator(timer,name='get')
class AddPublisher(View):
使用method_decorator和不使用的区别
1.传入装饰器函数的函数对象不同
2.inner函数获取参数不同
不使用:第一个参数为self,第二个为request对象
func——》<function AddPublisher.get at 0x000001FC8C358598>
args——》(<app01.views.AddPublisher object at 0x0001FC8C432C50>, <WSGIRequest: GET '/add_publisher/'>)
使用method_decorator之后:第一个参数为request对象
func——》<function method_decorator.<locals>._dec.<locals>._wrapper.<locals>.bound_func at 0x0015185F7C0D0>
args——》(<WSGIRequest: GET '/add_publisher/'>,)
request对象
当一个页面被请求时,Django就会创建一个包含本次请求原信息的HttpRequest对象。
Django会将这个对象自动传递给响应的视图函数,一般视图函数约定俗成地使用 request 参数承接这个对象。
# 属性
request.methot 请求方式 GET
request.GET url上携带的参数 QueryDict
request.POST POST请求提交的数据 QueryDict
request.path_info URL的路径 不包含ip和端口 不包含参数 /login/
request.META 请求头
request.body 请求体 b''
request.FILES 上传的文件
request.COOKIES cookie
request.session session
# 方法
request.get_full_path() URL的路径 不包含ip和端口 包含参数 /login/?name=xxx&pwd=123
request.is_ajax() 判断是都是ajax请求
上传文件实例
def upload(request):
"""
保存上传文件前,数据需要存放在某个位置。默认当上传文件小于2.5M时,django会将上传文件的全部内容读进内存。
从内存读取一次,写磁盘一次。
但当上传文件很大时,django会把上传文件写到临时文件中,然后存放到系统临时文件夹中。
:param request:
:return:
"""
if request.method == "POST":
# 从请求的FILES中获取上传文件的文件名,file为页面上type=files类型input的name属性值
filename = request.FILES["file"].name
# 在项目目录下新建一个文件
with open(filename, "wb") as f:
# 从上传的文件对象中一点一点读
for chunk in request.FILES["file"].chunks():
# 写入本地文件
f.write(chunk)
return HttpResponse("上传OK")
form需要属性enctype="multipart/form-data"才可以传文件。
Response对象
HttpResponse,render, redirect
from django.shortcuts import render, redirect, HttpResponse
HttpResponse('字符串') ——》 ’字符‘
render(request,'模板的文件名',{k1:v1}) ——》 返回一个完整的TML页面
redirect('重定向的地址') ——》 重定向 Location : 地址
设置或删除响应头信息
response = HttpResponse()
response['Content-Type'] = 'text/html; charset=UTF-8'
del response['Content-Type']
属性
HttpResponse.content:响应内容
HttpResponse.charset:响应内容的编码
HttpResponse.status_code:响应的状态码
JsonResponse
HttpResponse的子类,专门用来生成JSON编码的响应。
from django.http import JsonResponse
response = JsonResponse({'foo': 'bar'})
print(response.content)
# b'{"foo": "bar"}'
默认只能传递字典类型,如果要传递非字典类型需要设置一下safe关键字参数。
response = JsonResponse([1, 2, 3], safe=False)