Django的View(视图)、settings源码的解析、模板层
一、FBV与CBV视图函数并不只是指函数,也可以是类 FBV:基于函数的视图,类似面向函数式编程 CBV:基于类的视图,类似面向对象编程 ? ?研究解析render源码:render:返回html页面;并且能够给该页面传值 分析:FBV视图原理from django.shortcuts import render,HttpResponse # Create your views here. from django.template import Template,Context # FBV解析 def index(request): temp = Template(‘<h1>{{ user }}</h1>‘) con = Context({"user":{"name":‘gets‘,‘password‘:‘123456‘}}) res =temp.render(con) print(res) return HttpResponse(res) print的结果: ? ? ?可以分析出先获取数据格式,通过con = Context({"user":{"name":‘gets‘,‘password‘:‘123456‘}})转成字典形式传给前端显示 分析CBV视图原理:类方法问题:基于CBV的视图函数,get请求来就会走类里面get方法,post请求来就会走类里面post方法 为什么??? 为什么会自动分布请求类中的get/post方法呢?有什么在自动识别? #CBV视图 from django.views import View from django.conf import settings class MyLogin(View): def get(self,request): print("from MyLogin get方法") 为什么会走get/post return render(request,‘login.html‘) def post(self,request): return HttpResponse("from MyLogin post方法") ? ? ? CBV的路由层:url ? ? 由于函数名加括号执行优先级最高,所以这一句话一写完会立刻执行as_view()方法1、从url入手分析这一现象的存在:分析as_view源码解析结果:源码解析: @classonlymethod def as_view(cls,**initkwargs): # cls就是我们自己的写的类 MyLogin def view(request,*args,**kwargs): self = cls(**initkwargs) # 实例化产生MyLogin的对象 self = MyLogin(**ininkwargs) if hasattr(self,‘get‘) and not hasattr(self,‘head‘): self.head = self.get self.request = request self.args = args self.kwargs = kwargs # 上面的几句话都仅仅是在给对象新增属性 return self.dispatch(request,**kwargs) # dispatch返回什么 浏览器就会收到什么 # 对象在查找属性或者方法的时候 你一定要默念 先从对象自己这里找 然后从产生对象的类里面找 最后类的父类依次往后 return view ? ?通过源码发现url匹配关系可以变形成 url(r‘^login/‘,views.view) # FBV和CBV在路由匹配上是一致的 都是url后面跟函数的内存地址 ? 2、当浏览器中输入login,会立刻触发view函数的运行 ? ?第二部分分析源码: def dispatch(self,request,**kwargs): # Try to dispatch to the right method; if a method doesn‘t exist, # defer to the error handler. Also defer to the error handler if the # request method isn‘t on the approved list. # 我们先以GET为例 if request.method.lower() in self.http_method_names: # 判断当前请求方法是否在默认的八个方法内 # 反射获取我们自己写的类产生的对象的属性或者方法 # 以GET为例 handler = getattr(self,‘get‘,‘取不到报错的信息‘) # handler = get(request) handler = getattr(self,request.method.lower(),self.http_method_not_allowed) else: handler = self.http_method_not_allowed return handler(request,**kwargs) # 直接调用我们自己的写类里面的get方法 # 源码中先通过判断请求方式是否符合默认的八个请求方法 然后通过反射获取到自定义类中的对应的方法执行 ? 通过路由层url中的.re_view方法,解析源码分析得出实现get/post请求分发的原理,是什么请求就走什么方法 Django settings 源码解析:前提: 1、diango除了暴露给用户一个settings.py配置的文件之外,自己内部还有一个全局的配置文件(只是展示了部分信息的settnigs)。 2、我们在使用配置文件的时候,可以直接导入暴露给用户的settings.py也可以使用django全局的配置问的文件 需要导入的模块:from django.conf import settings ? 点击settings 查看源码配置文件 ? ? 3、django的启动入口是manage.py 分析为什么在settings配置文件中的变量名都是大写的?为什么写小写的就不行了呢? ? 基于以上分析源码后,分析实现seettings的功能,受限变量名必须写大写 import os import sys if __name__ == "__main__": # django在启动的时候 就会往全局的大字典中设置一个键值对 值是暴露给用户的配置文件的路径字符串 os.environ.setdefault("DJANGO_SETTINGS_MODULE","day54.settings") class Settings(object): def __init__(self,settings_module): # settings_module = ‘day54.settings‘ # update this dict from global settings (but only for ALL_CAPS settings) or setting in dir(global_settings): # django全局配置文件 # dir获取django全局配置文件中所有的变量名 if setting.isupper(): # 判断文件中的变量名是否是大写 如果是大写才会执行/生效 setattr(self,setting,getattr(global_settings,setting)) # 给settings对象设置键值对 # 给settings对象设置键值对 settings[配置文件中大写的变量名] = 配置文件中大写的变量名所对应的值 # store the settings module in case someone later cares self.SETTINGS_MODULE = settings_module # ‘day54.settings‘ mod = importlib.import_module(self.SETTINGS_MODULE) # mod = 模块settings(暴露给用户的配置文件) for setting in dir(mod): # for循环获取暴露给用户的配置文件中所有的变量名 if setting.isupper(): # 判断变量名是否是大写 setting_value = getattr(mod,setting) # 获取大写的变量名所对应的值 setattr(self,setting_value) # 给settings对象设置键值对 """ d = {} d[‘username‘] = ‘jason‘ d[‘username‘] = ‘egon‘ 用户如果配置了就用用户的 用户如果没有配置就用系统默认的 其实本质就是利用字典的键存在就是替换的原理 实现了用户配置就用用户的用户没配置就用默认的 """ ? ?继承的类分析: class LazySettings(LazyObject): def _setup(self,name=None): # os.environ你可以把它看成是一个全局的大字典 settings_module = os.environ.get(ENVIRONMENT_VARIABLE) # 从大字典中取值键为DJANGO_SETTINGS_MODULE所对应的值:day54.settings # settings_module = ‘day54.settings‘ self._wrapped = Settings(settings_module) # Settings(‘day54.settings‘) 作业:
|