Django框架之视图层与CBV与settings源码解析

Django框架之视图层与CBV与settings源码解析

视图函数必须要返回一个HttpResponse对象

返回的 render 和 redirect 本质上也是HttpResponse对象,所以视图函数必须要返回一个HttpResponse对象是正确的

1、JsonResponse

1、序列化字典对象,对象中要是有非ASCII码的字符需要将JSONResponse对象中的json_dumps_params = {'ensure_ascii': False} 默认为True变为False

from django.http import JsonResponse
user_dic = {'username':"Mr沈", 'password':'123'}
return JsonResponse(user_dic, json_dumps_params={'ensure_ascii': False})

2、序列化非字典格式数据,需要将safe改为False

from django.http import JsonResponse
l1 = [1,2,3,4,5]
return JsonResponse(l1, safe=False)

2、form表单上传文件数据

HTML文件中通过method='post' 和 enctype="multipart/form-data"让用户提交数据

<form action="" method="post" enctype="multipart/form-data">
    <input type="file" name="myfile">
    <input type="submit">
</form>

后端视图层可以通过request.FILES获取文件数据

def home(request):
    if request.method == 'POST':
        # 获取用户上传的文件数据
        print(request.FILES)
        file_obj = request.FILES.get('myfile')  # 文件句柄
        print(file_obj.name)  # 获取文件名
        with open(file_obj.name,'wb') as f:
                for line in file_obj:
                    f.write(line)
​
    return render(request,'home.html')

3、render原理

from django.template import Template, Context
def re_render(request):
    tem = Template('<h1>{{ user_dic }}{{ user_dic.username }}</h1>')
    user_dic = Context({'user_dic': {'username': 'vicky', 'password': 123}})
    res = tem.render(user_dic)
    return HttpResponse(res)

4、FBV和CBV

视图函数不一定就是一个函数,也可以是一个类

FBV:基于函数的视图,直接在视图层写的函数

CBV:基于类的视图,在视图层写类

1、CBV基本写法

1、首先在路由层中与视图函数对应关系应该调用类方法as_view()

url(r'^login/', views.MyLogin.as_view())

2、在视图层中,调用View模块,使定义的类继承该模块,在该类下写所有的请求方式方法

from django.views import View
class MyLogin(View):
    def get(self, request):
        return render(request, 'login.html')
    def post(self, request):
        return HttpResponse('收到post请求')

类中的方法as_view()能够自动识别提交的是什么请求执行MyLogin中的get或post方法

2、CBV源码

为什么调用as_view方法就能自动执行对应的方法呢?我们讲究需要看CBV源码了

1、首先as_view是由类来调用的,我们猜想是普通的函数静态方法 @staticmethod 或者是类的绑定方法 @classmethod 看源码发现是类的绑定方法

2、所以执行url就相当于执行view函数,接下来我们来看view函数干了什么

3、我们要确定self是我们自己写的类产生的对象,cls就是我们自己写的类,因此最后返回的self.dispatch会先从我们自己写的类的对象中查找,再从我们自己写的类中查找,如果没有再从继承的父类View中查找dispatch

4、最后我们得出dispatch就是分发不同的请求方式到我们自己写的类的对应的方法,从而执行对应的方法

总结:as_view()返回的结果是 ---> view,view()函数返回的结果是 ---> dispatch(),在dispatch中进行获取反射获取请求方式,从而调用我们自定义的类中的对应的方法,所以可以自动识别提交的是什么请求执行MyLogin中的对应的方法

5、settings配置源码解析

Django有暴露给用户的settings配置文件和内部自己默认的配置,我们需要看内部默认的配置时,首先在settings文件中导入global_settings和settings查看内部默认的配置

from django.conf import global_settings, settings

点击settings进入源码进入此页面可得到

importlib模块

可以通过字符串路径来获取路径中的属性和方法

import importlib
res = 'conf.b'
md = importlib.import_module(res)  # 此方法获取到对象
# 该方法最小单位是模块 不能是模块里面的单个名字
print(md.name)

总结:用户配置了就用用户的,用户没有配置就用默认的配置

手动模拟Django配置文件所做的事

import importlib
import os
from lib.conf import global_settings

class Settings(object):
    def __init__(self):
        # 先循环遍历项目默认的全局配置文件
        for name in dir(global_settings):
            # 判断变量名是否是大写
            if name.isupper():
                # 键值对设置给对象
                k = name  # NAME
                v = getattr(global_settings,name)  # jason
                setattr(self,k,v)

        # 先获取暴露给用户的配置文件的字符串路径
        module_path = os.environ.get('xxx')  # conf.settings
        # 里面importlib模块 导入settings文件
        md = importlib.import_module(module_path)  # md = settings

        # 同上操作
        for name in dir(md):
            # 判断变量名是否是大写
            if name.isupper():
                # 键值对设置给对象
                k = name  # NAME
                v = getattr(md,name)  # jason
                setattr(self,k,v)

settings = Settings()

 

 

posted @ 2020-01-08 00:53  Mr沈  阅读(143)  评论(0)    收藏  举报