Django源码剖析

Django配置文件

# django真正的配置文件
	from django.conf import global_settings
   	'''
   	settings.py只是django暴露给用户供用户自定义的配置文件
   	global_settings.py是django默认的全局配置文件
   	'''

# 如果用户在settings.py中自定义的配置则使用用户自定义的,否则使用默认的
    
# 暴露给用户的配置文件中有的配置,全局配置文件肯定有,暴露给用户的配置文件中没有的配置,全局配置文件也有

# 在django中导入配置文件正确的方式
	from django.conf import settings

Django配置文件源码剖析

from django.conf import settings
# 通过源码,可以发现这个settings是一个类
os.environ:内置的全局字典
settings_module = os.environ.get(ENVIRONMENT_VARIABLE)  # 获取暴露给用户的配置文件的字符串路径
self._wrapped = Settings(settings_module)  # 把路径字符串传给Settings类实例化

class Settings(object):
    def __init__(self, settings_module):
        for setting in dir(global_settings):  # 获取全局配置文件的配置名字
            if setting.isupper():  # 校验变量名是否是纯大写
                setattr(self, setting, getattr(global_settings, setting))  # 通过反射获取系统配置文件的所有的大写变量名和对应的值赋值给settings对象
self.SETTINGS_MODULE = settings_module
mod = importlib.import_module(self.SETTINGS_MODULE)  # 通过字符串路径导入模块
self._explicit_settings = set()
        for setting in dir(mod):  #循环获取用户自定义的配置文件的变量名
            if setting.isupper():
                setting_value = getattr(mod, setting)  # 获取变量名对应的值

                if (setting in tuple_settings and
                        not isinstance(setting_value, (list, tuple))):
                    raise ImproperlyConfigured("The %s setting must be a list or a tuple. " % setting)
                setattr(self, setting, setting_value)  # 把变量名和变量值添加到对象里面
                self._explicit_settings.add(setting)

# 用户在settings.py中自定义的配置则使用用户自定义的,否则使用默认的配置原理:
	在Settings类中,执行了两次加载配置的操作,先加载global_settings的配置,然后加载用户项目中的settings,如果用户自定义了配置,则global_settings的配置会被替换

基于settings源码编程

# 基于settings源码编程,原理就是设置好默认的参数,暴露给用户一个可以修改的文件,先加载系统默认参数并赋值给settings对象,再加载用户自定义参数,如果用户自定义了参数则把系统默认参数替换掉

权限管理简介

# web领域的权限就是url
	'''
	本质就是在用户访问资源时,获取该用户的访问权限,如果有权限,则允许访问该url,如果没有权限则拒绝访问
	'''
    
# 权限设计
	用户表
    id			name		pwd
    1			a			aaa
    2			b			bbb
   	3			c			ccc
    权限表
    id			permission
    1			添加数据
    2			修改数据
    3			删除数据
    用户_权限关系表
    user_id			permission_id
    1				1	
    1				2
    2				3
    3				1
'''
缺点:
	用户多了第三张表关系非常复杂
'''

RBAC

用户表
id			name		pwd
1			a			aaa
2			b			bbb
3			c			ccc
角色表
id			role		
1			CEO
2			保安
3			保洁
权限表
id			permission
1			添加数据
2			修改数据
3			删除数据
用户_角色关联表
user_id		role_id
1			1
2			3
3			2
角色_权限关联表
id			role_id			permission_id
1			1				1	
2			2				2
3			3				3
'''
后续添加权限只需要添加角色即可,无需再去该权限关联表
'''

RBAC实战

# 进行权限校验主要通过中间件实现功能
# 自定义中间件process_request方法,这个方法会在请求来的时候触发,我们在用户登录时获取用户权限,绑定到session中,在process_request方法中进行校验当前访问路径是否有权限,有则允许访问,无则拦截本次访问

# 自定义中间件
from django.utils.deprecation import MiddlewareMixin
import re
from django.http import HttpResponse
class MyPermission(MiddlewareMixin):
    def process_request(self,request):
        # 定义白名单,不需要权限也可访问
        white_url = ['/login/','/register/']
        # 1.获取请求地址
        target_url = request.path
        # 如果访问的url在白名单中,直接放行
        re_path = '^%s$'%target_url
        for url in white_url:
            res = re.search(re_path,url)
            if res:
                return 
        # 2.获取session中的权限列表
        permission_url = request.session.get('permission_list')
        # 3.判断用户是否有权限访问当前url
        for url in permission_url:
            res = re.search(re_path, url)
            if res:
                return
        return HttpResponse('当前访问地址无权限')
    
'''
拓展延伸:
	1.黑名单
	2.校验访问频率
'''

admin配置

# 在注册模型表的时候,可以添加配置
class Userconfig(models.User):
    list_display = ['username','password','age']  # 控制展示字段
    list_display_links = ['password']  # 控制字段跳转
    search_fields = ['username','age']  # 通过搜索框查找对应字段
    list_filter = ['username']  # 筛选框 一般填外键名
    def patch_init(self,request,queryset):  # queryset操作函数
        queryset.update(age = F('age')+1)
    patch_init.short_description = '批量年龄加一'  # 定义功能名字
    actions = [patch_init,]  # 自定义queryset操作