Django-视图层

1.视图层之必会三板斧

"""
用来处理请求的视图函数都必须返回HttpResponse对象:完全正确。因为。
"""

	
1.查看源码我们得知,render功能的返回值是一个HttpResponse对象,说明它们都是有HttpResponse对象演变而来的
def render():
	return HttpResponse()
# 5

2.redirect继承的不是HttpResponse,但是祖先有个类是HttpResponse,所以redirect对象也是HttpResponse对象。
def redirect(to, *args, permanent=False, **kwargs):
	redirect_class = 类(祖先有个类是HttpResponse)
	return redirect_class(resolve_url(to, *args, **kwargs))
"""
综上所述:用来处理请求的视图函数都必须返回HttpResponse对象。
"""

2.视图层之JsonResponse对象

1.JsonResponse对象可以将后端的字段数据直接变成Json格式在页面显示。
模块导入:from django.http import JsonResponse
    
views:    
def register(request):
    userdict = {'name':'max', 'age':25}
    return JsonResponse(userdict)

2.但是当我们传入中文之后,发现中文依旧会乱码。
"""
在json.dump()中有一个参数是ensure_ascii=Flase,这个参数可以控制中文是否编码。我们查看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(data, cls=encoder, **json_dumps_params)中有一个参数json_dumps_params是字典类型,并且前面带**说明可以将字典打散成关键字参数。所以我们直接给json_dumps_params字典指定一个值{'ensure_ascii':False},**会将字典打散成关键字参数传入。return JsonResponse(userdict,json_dumps_params={'ensure_ascii':False})
"""


3.当我们想要将其他数据类型序列化转世在页面上,依然可以通过看源码的方式得到:需要加一个参数safe=False"""
源码:
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.'
            ) 
"""
   
def login(request):
    userlist = [1, 'jason', 2, 'max', (1,2,3)]
    return JsonResponse(userlist,safe=False)

3.视图层之request对象获取文件

form表单携带文件类型必须要做到以下几点:
"""
当我们输入以下代码,并且通过request.POST拿到用户数据字典之后,我们发现文件的name对应的是一个文件名:
"""

	1.method表单必须是post(因为get)。
	2.form标签中enctype对应的值必须是multipart/form-data。
	3.django后端需要通过request.FILE获取文件类型的数据。
获取到的是一个文件对象:  

我们可以通过文件读写的方式,让获取到的文件保存到指定位置:
views:
def info(request):
    if request.method == 'POST':
        print(request.POST)
        print(request.FILES)
        file_obj = request.FILES.get('file')
        print(file_obj.name)
        with open(r'%s'%file_obj.name, 'wb') as f:
            for line in file_obj:
                f.write(line)
    return render(request,'index.html')

4.视图层之FBV与CBV

1.FBV:基于函数的视图。
def index(request):
	return HttpResponse('字符串')

2.CBV:基于类的视图,用面向对象报的语法来写视图层功能。
views:
from django 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')
    
urls:
urlpatterns = [
    path('login1/', views.MyLoginView.as_view())
]
会自动根据请求方法的不同自动匹配对应的方法并执行:
当我们访问login1/路由时,会向服务端MyLoginView发送一个get请求,因为类中有get方法,所以会直接返回HttpResponse('from CBV get function')。
当我们访问其他页面时,向login1/路由提交数据,会触发类中post方法,返回HttpResponse('from CBV post function')。

5.CBV源码剖析(重要)

1.我们想要查看CBV源码,从路由层入手:
urls:
urlpatterns = [
    path('login1/', views.MyLoginView.as_view()),
]

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')
MyLoginView是一个类,类名点一个名字首先去类中查找,但是类MyLoginView中没有as_view名字,并且该名字还加了括号。再去父类views.View中查找。

2.在父类View中,有一个绑定给类的as_view方法,并且函数名加括号,优先级最高:

并且在as_view方法中,还有一个view函数,并且该函数的返回值是view,所以
 views.MyLoginView.as_view()会变形称为:views.view。此时
urlpatterns = [
    path('login1/', views.view),
]
类似于FBV中的方法,所以CBV的本质还是FBV。

3.cls是我们定义的类MyLoginView,所以self=cls(),self是类MyLoginView的一个对象。
view函数的返回之是:return self.dispatch(request, *args, **kwargs)。
self是一个对象,对象点名字首先要在对象名称空间中查找,我们暂未给该对象添加任何名字,找不到,然后再到类名称空间中查找,类中只有get和post两个名字。
所以继续到父类中查找,发现有dispatch函数(如果我们在MyLoginView中定义一个dispatch方法就会优先查找到类中的dispatch):

4.dispatch函数体代码:
    def dispatch(self, request, *args, **kwargs):
        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)
我们发现分支结构中的if:request.method.lower()就是我们的GET/POST请求,lower()转为小写。http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace']。显然request.method.lower()在http_method_names中。所以走if分支。if分支中:类中有post/get方法,所以反射拿到一个post/get的结果并且返回。
posted @   ERROR404Notfound  阅读(17)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律
Title
点击右上角即可分享
微信分享提示