Django的View(视图)settings源码的解析模板层
Posted gaimo
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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, *args, **kwargs) # dispatch返回什么 浏览器就会收到什么 # 对象在查找属性或者方法的时候 你一定要默念 先从对象自己这里找 然后从产生对象的类里面找 最后类的父类依次往后 return view
通过源码发现url匹配关系可以变形成
url(r‘^login/‘,views.view) # FBV和CBV在路由匹配上是一致的 都是url后面跟函数的内存地址
2、当浏览器中输入login,会立刻触发view函数的运行
第二部分分析源码:
def dispatch(self, request, *args, **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, *args, **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, 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‘)
settings = LazySettings() # 单例模式
作业:
参考django settings源码 实现自己的项目也能够做到 用户配置了就用用户的 用户没有配置 就用全局的
__init__.py文件下:
import os import importlib from lib.conf import global_settings class Settings(object): def __init__(self): # 先for循环获取全局配置文件中所有的变量名 for name in dir(global_settings): # 判断是否是大写 if name.isupper(): #给settings对象设置键值对 setattr(self,name,getattr(global_settings,name)) path = os.environ.get(‘xxx‘) module = importlib.import_module(path) #再循环暴露给用户的文件中所有的变量名 for name in dir(module): if name.isupper(): k=name v=getattr(module,name) setattr(self,k,v) settings=Settings()
start.py文件
import os import sys BASE_DIR = os.path.dirname(__file__) sys.path.append(BASE_DIR) if __name__ == ‘__main__‘: # 在项目中的全局一个大字典 os.environ.setdefault(‘xxx‘,‘conf.settings‘) from lib.conf import settings print(settings.NAME)
Django模板层
模板语法
只需要记两种特殊符号: 和 % % 变量相关的用,逻辑相关的用%%。
以上是关于Django的View(视图)settings源码的解析模板层的主要内容,如果未能解决你的问题,请参考以下文章
Django drf:cbv(class base view)源码分析