一、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源码的解析、模板层的详细内容...