视图层之必会三板斧
用来处理请求的视图函数都必须返回HttpResponse对象 完全正确
使用HttpResponse返回的时候,代码实际如下;
class HttpResponse()
pass
return HttpResponse 所以实际上返回的是HttpRespinse加括号产生的对象
使用render返回的时候,实际代码如下:
def render():
return HttpResponse()
接收到返回值再交给我们的render()返回,实际上我们调用render返回的源代码返回的是还是一个HttpResponse对象
使用redirct返回的时候,实际代码如下:
def redirect():
redirect_class = 类(祖先有个类是HttpResponse)
return redirect_class()
接收到返回值实际还是HttpResponse的后代类产生的对象,也可以理解为HttpResponse产生的对象,最后返回的最后还是HttpResponse产生的对象
JsonResponse对象
JsonResponse主要作用是直接将我们的数据格式转为json格式发送到页面,不需要用json模块先转json字符串格式再发送
def index_func(request):
# 返回给浏览器一个json格式的字符串
user_dict = {'name': 'jason老师', 'age': 18}
return JsonResponse(user_dict) # 页面直接显示json格式的字符串
相对于json模块来说,节省了代码
以后写代码很多时候可能需要参考源码及所学知识扩展功能:
修改字符编码:
class JsonResponse(HttpResponse): "我们返回的是JsonResponse对象,所以加括号是调用了我们源代码的类产生了一个对象"
def __init__(self, data, encoder=DjangoJSONEncoder, safe=True,
json_dumps_params=None, **kwargs):
if safe and not isinstance(data, dict):
raise TypeError(
'In order to allow non-dict objects to be serialized set the '
'safe parameter to False.'
)
if json_dumps_params is None: "最重要的在这里这个值没有传,那么就是一个空字典"
json_dumps_params = {}
kwargs.setdefault('content_type', 'application/json')
data = json.dumps(data, cls=encoder, **json_dumps_params) "会在这里将空字典打散"
super().__init__(content=data, **kwargs)
那么:我们如果将json_dumps_params传值,肯定就就不会走if这个条件打散之后就会变成aaa=bbb这样的,我们想要中文编码需要写 ensure_ascii=Fales,就可以改变这里的值,写为{ensure_ascii:Fales}等待打散即可
def index_func(request):
# 返回给浏览器一个json格式的字符串
user_dict = {'name': 'jason老师', 'age': 18}
return JsonResponse(user_dict,json_dumps_params={'ensure_ascii': False}) # 页面直接显示json格式的字符串
视图层之request对象获取文件
form表单携带文件类型的数据需要做到以下几点
1.method必须是post
2.enctype必须是mulitipart/form-data
enctype="multipart/form-data"
django后端需要通过request.FILES获取文件类型的数据
date_file = request.FILES.get('文件名')
代码展示视图层:
def index_func(request):
if request.method == 'POST':
date_file = request.FILES.get('file')
with open(r'a.xtx', 'wb') as f:
for i in date_file:
f.write(i)
return HttpResponse('提交成功')
return render(request, 'index.html')
html页面:
<form action="" method="post" enctype="multipart/form-data">
<p>name:
<input type="text" name="name">
</p>
<p>文件
<input type="file" name="file">
</p>
<input type="submit" value="提交">
</form>
视图层之FBV与CBV
FBV
基于函数的视图
def index(request):return HttpResponse对象
CBV
基于类的视图
视图层:
class MyLogin(views.View):
def get(self, request):
return HttpResponse('from CBV get')
def post(self, request):
return HttpResponse('from CBV post')
路由层:
path('login/', views.MyLogin.as_view())
CBV:会根据请求方法的不同自动匹配对应的方法并执行
CBV源码剖析(重要)
路由层:
path('login/', views.MyLogin.as_view())
1.我们由路由层切入,因为发现路由匹配跟函数的不同,FBV是直接点函数名就可以了,CBV却是要类名点一个as_view()这样的一个方法
2.函数名加括号执行优先级最高,那么项目只要一启动就会自动执行as_vies()函数,查看源代码发现这个方法是绑定给类的方法,这个方法首先会类加括号产生一个对象,这个类就是我们创建的类,对象也就是我们创建的类锁产生的对象,返回值是"return self.dispatch(request, *args, **kwargs)",也就是对象点了dispatch方法,这个方法在我们对象以及我们所写的类中是不存在的,那么可能的就是我们类继承的父类
3.找到继承父类中的dispatch方式
代码如下:
if request.method.lower() in self.http_method_names:
handler = getattr(self, request.method.lower(), self.http_method_not_allowed)
else:
handler = self.http_method_not_allowed
return handler(request, *args, **kwargs)
这个获取当前的请求并转小写,判断是否在8种请求中,如果在的话,利用反射获取字符串对应的函数体代码,赋值给handler,最后handler加括号返回出去,也就是执行了请求对应的函数
代码浓缩展示:
class View:
@classmethod
def as_view(cls, **initkwargs): 先执行函数名加括号
def view(request, *args, **kwargs):
self = cls(**initkwargs)
return self.dispatch(request, *args, **kwargs) 返回对象调用dispatch方法
def dispatch(self, request, *args, **kwargs):
handler = getattr(self, request.method.lower()) 反射获取字符串对应的函数的函数体代码
return handler(request, *args, **kwargs) 返回加括号执行