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模板层

  模板语法

只需要记两种特殊符号:
{{  }}和 {% %}
变量相关的用{{}},逻辑相关的用{%%}。

  

猜你喜欢

转载自www.cnblogs.com/Gaimo/p/11546390.html