目录
django之视图层
视图层必会三板斧
用来处理请求的视图函数都必须返回HttpResponse对象
1. return HttpResponse() # HttpResponse本身是一个类,类加括号产生对象
2. return render()
源码见图二,render的源码是一个函数,返回值是HttpResponse(content, content_type, status),产生的也是HttpResponse对象
3. return redirect()
源码见图二,redirect的源码是一个函数,里面写了一个三元表达式
redirect_class = HttpResponsePermanentRedirect if permanent else HttpResponseRedirect
产生的结果都是HttpResponse,那么其返回值也是HttpResponse对象
图二
JsonResponse对象
正常情况下我们要给浏览器返回一个json格式的字符串需要先把字符串转为json格式然后再发送给浏览器
django中有一个JsonResPonse对象它可以直接完成上面的操作\
下面的是JsonResponse的源码
class JsonResponse(HttpResponse):
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)
1.使用JsonResponse传汉字,加一个json_dumps_params = {'ensure_ascii': False}
其它的一些可能需要使用到的参数如果没有默认的可以使用json_dumps_params
2.针对非字典的其它可以被序列化的数据需要修改safe参数为False safe=False
from django.http import JsonResponse
def index(request):
a = {'name': 'jason老师'}
b = [1, 2, 3, 4]
# return JsonResponse(a, json_dumps_params={'ensure_ascii': False})
return JsonResponse(b, json_dumps_params={'ensure_ascii': False}, safe=False)
request对象获取文件
form表单携带文件需要做到以下几点
1.method必须是post
2.enctype必须是multipart/form-data
# 在form表单中修改enctype参数为multipart/form-data,默认是application/x-www-form-urlencoded
django后端需要通过request.FILES来获取文件类型的数据,获取到的是一个文件对象
接收文件和GET、POST一样用get
file_obj = request.FILES.get('file')
file_obj.name # 获取文件名
# 文件对象支持for循环一行行读取文件内容
FBV与CBV
FBV 基于函数的视图
def index(request): return HttpResponse对象
CBV 基于类的视图
from diango import views
class MyLoginView(views.View):
def get(self, request):
return HttpResponse('from CBV get function')
def post(self, request):
return HttpResponse('from CBV post function')
path('login/', views.MyLoginView.as_view())
使用CBV会根据请求方法的不同自动匹配对应的方法并执行
CBV源码解析
1.先看路由匹配
path('login/', views.MyLoginView.as_view())
1.MyLoginView使我们自己定义的类,类点一个名字涉及到名字的查找顺序,自己没有往父类找
2.类名点名字加括号调用表明是一个绑定给类的方法(@classmethod)
2.函数名或方法名加括号执行优先级最高,项目一启动就会自动最先执行as_view方法
通过查看源码可以看到as_view方法的返回值是定义在as_view内部的view方法,那么我们的路由匹配就可以看成是
path('login/', views.view) # 由此可以看出CBV的本质还是FBV
源码:
@classonlymethod
def as_view(cls, **initkwargs):
"""Main entry point for a request-response process."""
for key in initkwargs:
if key in cls.http_method_names:
raise TypeError("You tried to pass in the %s method name as a "
"keyword argument to %s(). Don't do that."
% (key, cls.__name__))
if not hasattr(cls, key):
raise TypeError("%s() received an invalid keyword %r. as_view "
"only accepts arguments that are already "
"attributes of the class." % (cls.__name__, key))
def view(request, *args, **kwargs):
self = cls(**initkwargs)
if hasattr(self, 'get') and not hasattr(self, 'head'):
self.head = self.get
self.setup(request, *args, **kwargs)
if not hasattr(self, 'request'):
raise AttributeError(
"%s instance has no 'request' attribute. Did you override "
"setup() and forget to call super()?" % cls.__name__
)
return self.dispatch(request, *args, **kwargs)
view.view_class = cls
view.view_initkwargs = initkwargs
# take name and docstring from class
update_wrapper(view, cls, updated=())
# and possible attributes set by decorators
# like csrf_exempt from dispatch
update_wrapper(view, cls.dispatch, assigned=())
return view
3.由第二步可以得到浏览器访问login路由需要执行view函数
1.执行view函数会产生一个我们自己编写的类的对象
2.这个对象会调用dispatch方法
源码:
def view(request, *args, **kwargs):
self = cls(**initkwargs) # cls是我们自己编写的类,这一步是产生一个我们自己编写的类的对象
if hasattr(self, 'get') and not hasattr(self, 'head'):
self.head = self.get
self.setup(request, *args, **kwargs)
if not hasattr(self, 'request'):
raise AttributeError(
"%s instance has no 'request' attribute. Did you override "
"setup() and forget to call super()?" % cls.__name__
)
return self.dispatch(request, *args, **kwargs) # 我们自己编写的类的对象调用dispath方法
4.由于我们自己编写的类中没有dispatch方法,所以从父类中找
通过研究父类中的dispatch方法可以知道该方法是获取当前的请求方法并转小写,然后利用反射获取类中对应的方法并执行
源码:
def dispatch(self, request, *args, **kwargs):
# 判断转小写之后的请求方法是不是属于八个正常的请求方法
if request.method.lower() in self.http_method_names:
# getattr(对象,'get', '获取不到的报错信息')
handler = getattr(self, request.method.lower(), self.http_method_not_allowed)
else:
handler = self.http_method_not_allowed
return handler(request, *args, **kwargs) # 执行反射之后获取到的方法
标签:return,self,request,视图,django,json,view,cls
From: https://www.cnblogs.com/zyg111/p/16980563.html