[Django框架之视图层]
视图层
Django视图层, 视图就是Django项目下的views.py文件,它的内部是一系列的函数或者是类,用来专门处理客户端访问请求后处理请求并且返回相应的数据,相当于一个中央情报处理系统
小白必会三板斧
HttpResponse
- 返回字符串类型的数据
render
- 返回html页面,还可以使用模板语法
redirect
- 重定向
三板斧本质
django视图函数必须要返回一个HttpResponse对象? 正确!
django视图函数必须有一个返回值,并且返回值的数据类型必须是HttpResponse对象
# 研究三者源码可以得出结论
# HttpResponse
class HttpResponse(HttpResponseBase):
"""
An HTTP response class with a string as content.
# 以字符串作为内容的HTTP响应类
This content that can be read, appended to or replaced.
# 可以读取、添加或替换的内容
"""
streaming = False
def __init__(self, content=b'', *args, **kwargs):
super(HttpResponse, self).__init__(*args, **kwargs)
# 内容是一个字节串。参见' content '属性方法
# Content is a bytestring. See the `content` property methods.
self.content = content
# render
def render(request, template_name, context=None, content_type=None, status=None, using=None):
"""
Returns a HttpResponse whose content is filled with the result of calling
django.template.loader.render_to_string() with the passed arguments.
# 返回一个HttpResponse,它的内容中填充了调用的结果
# django.template.loader.render_to_string()和传递的参数
"""
content = loader.render_to_string(template_name, context, request, using=using)
return HttpResponse(content, content_type, status)
# redirect内部是继承了HttpRespone类
JsonResponse
给前端返回json格式的字符串
方式1:自己序列化
import json
def func(request):
d = {'user':'jason好帅','password':123}
res = json.dumps(d,ensure_ascii=False)
return HttpResponse(res)
方式2: JsonResponse
from django.http import JsonResponse
def func(request):
d = {'user':'jason好帅','password':123}
return JsonResponse(d)
# return JsonResponse(d,json_dumps_params={'ensure_ascii':False} )
ps:额外参数补充
json_dumps_params={'ensure_ascii':False} # 看源码
safe=False # 看报错信息
# JsonResponse返回的也是HttpResponse对象
上传文件
前端form表单上传文件注意事项
1.method必须是post
2.enctype参数需要修改为multipart/form-data
后端暂时需要注意的是
1.配置文件中注释掉csrfmiddleware中间件
2.通过request.FILES获取用户上传的post文件数据
def func3(request):
if request.method == 'POST':
print(request.POST)
file_obj = request.FILES.get('myfile')
print(file_obj.name) # 获取文件名称
with open(r'%s'%file_obj.name,'wb') as f:
for chunks in file_obj.chunks():
f.write(chunks)
return render(request,'func3.html')
FBV与CBV
FBV 基于函数的视图
FBV使用频率较低(基础阶段)
CBV 基于类的视图
CBV实际开发项目使用频率较高(高级阶段)
views.py视图层
视图函数
不仅仅可以是函数也可以是类
1.面向过程式编程
2.面向对象式编程
FBV基于函数的视图(Function base view)我们前面写的视图函数都是FBV
CBV基于类的视图(Class base view)
视图文件中除了用一系列的函数来对应处理客户端请求的数据逻辑外,还可以通过定义类来处理相应的逻辑
CBV基本使用
# views.py
from django.shortcuts import render,HttpResponse,redirect
from django.views import View
class MyView(View):
def get(self,request):
return HttpResponse("get方法")
def post(self,request):
return HttpResponse("post方法")
# urls.py
url(r'^func4',views.MyView.as_view())
"""为什么能够自动根据请求方法的不同执行不同的方法"""
1. CBV与FBV路由匹配本质
# urls.py
urlpatterns = [
url(r'^func4',views.MyView.as_view()) # CBV写法
# 等价 CBV路由配置本质跟FBV一样
url(r'^func4',views.view) # FBV写法
]
2. CBV与FBV区别之突破口
知识点:函数名/方法名:加括号执行优先级最高
CBV写的是 as_view() 加括号意味着在项目启动就会执行
那么我们大胆猜测:
要么是被@staicmethod修饰的静态方法,就是个普通函数没有形参
要么是被@classmethod修饰的类方法,类来调自动将类当做第一个参数传入
3. 研究一下源码
@classonlymethod # 类方法,就把它看成@classmethod
def as_view(cls, **initkwargs):
def view(request, *args, **kwargs): # view是as_view的闭包
self = cls(**initkwargs) # self = MyView()生成一个我们自己写的类的对象
"""
实例化出一个View类的对象,返回一个dispatch()函数,看着跟我们之前写的
视图函数几乎一毛一样,那么我们找一下函数的上级函数没有这个方法,最后在类
里发现了这个dispatch()函数
"""
return self.dispatch(request, *args, **kwargs)
return view # 返回一个函数的内存地址
def dispatch(self, request, *args, **kwargs):
# 获取当前请求并判断是否属于正常的请求(8个)
if request.method.lower() in self.http_method_names:
# get请求 getattr(对象,'get') handler = 我们自己写的get方法
handler = getattr(self, request.method.lower(), self.http_method_not_allowed)
else:
handler = self.http_method_not_allowed
return handler(request, *args, **kwargs) # 执行我们写的get方法并返回该方法的返回值
# 结论:as_view()最终干的事情就是根据request请求方式来执行视图类的不同请求方法
总结:以后会经常需要看源码,但是在看Python源码的时候,一定要时刻提醒自己面向对象属性方法查找顺序,先从对象自己找,再去产生对象的类里面去找,之后再去父类找,看源码只要看到了self点一个东西,一定要问自己当前这个self到底是谁。