django 之 视图层、模板层

目录

视图层

一.视图函数返回的都是一个HttpResponse对象

render 和 redirect 都是直接或者间接传的

二.JsonResponse

下面这个是正常的json的序列化

views.py 层
def test1(request):
    user_dict={'username':'jason 顶天立地 ','password':123}
    json_str= json.dumps(user_dict,ensure_ascii= False)###保证中文不会转成bytes
    return HttpResponse(json_str)
浏览器展示的:
{"username": "jason 顶天立地 ", "password": 123}

JsonResponse 序列化

from django.http import JsonResponse

def test1(request):
    user_dict={'username':'jason 顶天立地 ','password':123}
    # json_str= json.dumps(user_dict,ensure_ascii= False)

    return JsonResponse(user_dict,json_dumps_params={'ensure_ascii':False})#后面的这个代表的是保证中文不会转成bytes
浏览器展示的:
{"username": "jason 顶天立地 ", "password": 123}

如果序列的不是字典样式

def test1(request):
    # user_dict={'username':'jason 顶天立地 ','password':123}
    # json_str= json.dumps(user_dict,ensure_ascii= False)
    l1=[1,'磁场强大','人缘极好']
    return JsonResponse(l1,json_dumps_params={'ensure_ascii':False},safe=False)###最后safe为False这个保证非字典 也可以识别
浏览器展示的:
[1, "磁场强大", "人缘极好"]

三.form表单的上传

home.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
    <link href="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">
    <script src="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/js/bootstrap.js"></script>
</head>
<body>
<form action="" method="post"enctype="multipart/form-data">
   username: <input type="text"name="username">
    password: <input type="text" name="password">
    <p><input type="file" name="myfile"></p>

    <input type="submit">

</form>
</body>
</html>

views.py

def test1(request):
      if request.method == 'POST':
        print(request.FILES)
        file_obj= request.FILES.get('myfile')
        print(file_obj.name)
        with open(file_obj.name,'wb') as f:
            for line in file_obj:
                f.write(line)   ###把图片保存起来
    return render(request,'home.html')
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
<MultiValueDict: {'myfile': [<InMemoryUploadedFile: 333.png (image/png)>]}>
333.png

FILES可以通过这个拿到文件
注意:form表单上传文件
            1.必须做的事
                method必须是post
                enctype必须是formdata
            2.暂时需要做的 
                提交post请求需要将中间件里面的一个csrfmiddleware注释掉
            
            后端如何获取用户上传的文件
                file_obj = request.FILES.get('前端input框name属性值')
                file_obj.name  # 文件名
                for line in file_obj:
                    print(line)
                
                # django中推荐以下写法
                for chunk in file_obj.chunks():
                    print(chunk)

四.ab_render的原理

from django.template import Template,Context

def ab_render(request):
    temp=Template('<h1>{{user_dict}}</h1>')
    user_dict = Context({'user_dict':{'username':'jason','password':123}})
    res= temp.render(user_dict)
    return HttpResponse(res)
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
浏览器显示的:
{'username': 'jason', 'password': 123}

五.FBV 和CBV

视图函数并一定就是函数 也可以是类

FBV:基于函数的视图

CBV:基于类的视图

下面是CBV的类的视图

urls

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^ab_render/', views.ab_render),
    url(r'^login/', views.MyLogin.as_view()), #这个是路由与视图函数对应关系相当于url(r'^login/', views.view)
]

views

from django.views import View
class MyLogin(View):
    def get(self,request):
        return render(request,'login.html')

    def post(self,request):
        return HttpResponse('我是类里面post的方法')

login.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
    <link href="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">
    <script src="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/js/bootstrap.js"></script>
</head>
<body>
<form action=""method="post">
    <input type="submit">
</form>

</body>
</html>

遇到上面的这个我们需要考虑一下,并且考虑 一些源码的问题

朝login提交get请求会自动执行MyLogin里面的get方法
而提交post请求也会自动执行MyLogin里面的post方法
为什么MyLogin针对不同的请求方法能够自动执行对应的方法

研究源码的突破口
        url(r'^login/',views.MyLogin.as_view())
        猜想
            as_view要么是类里面定义的普通函数 @staticmethod
            要么是类里面定义的绑定给类的方法  @classmethod
        看源码发现是绑定给类的方法

django 之  视图层、模板层
django 之  视图层、模板层

CBV源码(******)
                MyClass.as_view()
                # 函数名加括号执行优先级最高
                @classonlymethod
                def as_view(...):
                    def view(...):
                        ...
                    return view
                # 变形
                url(r'^index/',views.view)  # CBV与FBV在路由匹配上本质是一样的
                
                def view(...):
                    self = cls(...)  # 生成的是我们自己写的类的对象
                    ...
                    return self.dispatch(...)
                    """
                    当你看到self.属性或方法的时候 不要想当然 
                    一定要遵循对象的属性和方法的查询顺序
                    对象本身  产生对象的类  类的父类
                    """
                def dispatch(...):
                    # 先判断当前请求方式是否在默认的八个合法请求方式内
                    if request.method.lower() in ['get','post','delete','options'...]
                        # 利用反射获取对象中对应的属性
                        handler = getattr(self,request.method.lower(),报错信息)
                    
                    return handler(...)  # 执行获取到的方法

FBV和 CBV在路由匹配上本质是一样的,都是路由和函数内存地址的对应关系

六.importlib

我们正常的通过模块可以获取模块里面的值

conf包 里面有b.py
name= 'david'

a.py
# from conf import b
# print(b.name)
>>>>>>>>>>>>>>>>>>>>
david

上面的我们可以用其他的importlib来写

conf包 里面有b.py
name= 'david'

a.py 
import importlib
res= 'conf.b'
md=importlib.import_module(res)
#该方法的最小单位是模块 不是模块里面的单个名字
print(md.name)
>>>>>>>>>>>>>>>>>>>>
david

模板层

一.模板传值

python基本数据类型全部支持传递给html文件
        函数
        类
            函数和对象会自动加括号
            # 模板语法不支持传参
        对象
            后端给html文件传递数据的两种方式
            1.指名道姓
                return render(request,'index.html',{'n':n,'f':f})###放在一个字典里

            2.locals()  # 会将当前名称空间中所有的变量名全部传递给html页面
                return render(request,'index.html',locals())  
        
            html页面上 如何获取到后端传递过来的数据 
                {{ 变量名 }}
    
        取值
            django模板语法取值 只有一种操作方式  句点符 .
            点索引
            点键
            
            <p>{{ l.2 }}</p>
            <p>{{ d.username }}</p>
            <p>{{ d.password }}</p>
            <p>{{ d.hobby.1.username.1 }}</p>

8种数据类型和函数 、类 、对象传递给html文件

views

def index(request):
    #python的所有的数据类型都支持传递给html页面
    n=11
    f=11.111
    s='hello world'
    l=[1,2,3,4,5,6]
    d={'username':'jason','password':123,'hobby':['read',{'username':['egon','jason']}]}
    t=(1,2,3,4,5,6,)
    se={1,2,3,4,5}
    b= True
    ff= False
    ss='dsdkljgjsg sjg;d  djle dejs;egl dee kd;le;lk '
    sss='是的K歌 警方介入进来大家多 罚款交了比较 房间里人家给 外婆'
    file_size= 3290237579476
    def func():
        print('func 被执行了')
        return 'from func'

    class MyClass(object):
        def get_self(self):
            return 'from self'

        @staticmethod
        def get_func():
            return 'from func'

        @classmethod
        def get_cls(cls):
            return 'from cls'
    obj = MyClass()

    return render(request,'index.html',locals())

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
    <link href="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">
    <script src="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script>
</head>
<body>
{#<p>{{ n }}</p>#}
{#模板语法的注释  这个注释前端浏览器检查是看不见的#}
<!--浏览器检查能够看到-->
{#<p>{{ f }}</p>#}
{#<p>{{ s }}</p>#}
{#<p>{{ l }}</p>#}
{#<p>{{ d }}</p>#}
{#<p>{{ t }}</p>#}
{#<p>{{ se }}</p>#}
{#<p>{{ b }}</p>#}
{#<p>函数名会自动加括号执行 展示的是函数的返回值:{{ func }}  模板语法不支持给函数传参</p>#}

{#<p>传类名 也会自动加括号实例化 拿到的是对象地址{{ MyClass }}</p>#}
{#<p>{{ MyClass }}</p>#}
{#<p>{{ MyClass.get_func }}</p>#}
{#<p>{{ MyClass.get_cls }}</p>#}
{#<p>{{ MyClass.get_self }}</p>#}
{#<p>{{ obj }}</p>#}  ##得到的是对象的地址
{#<p>{{ obj.get_func }}</p>#}
{#<p>{{ obj.get_self }}</p>#}
{#<p>{{ obj.get_cls }}</p>#}

{#<p>取值</p>#}
{#<p>{{ l.2 }}</p>#}
{#<p>{{ d.username }}</p>#}
{#<p>{{ d.password }}</p>#}
{#<p>{{ d.hobby.1.username.1 }}</p>#}
</body>
</html>

二.模板的过滤器

如下是具体的语法
    |length:求长度
    |add:增加值
    |default :设置默认值 如果是True 返回True  如果是false  返回默认值
    |truncatechars: 截取字符  后面加3个点
    |truncatewords:截取单词  后面加3个点
    |filesizeformat:文件大小 换算成多少B
    |slice :切片
    |date:  转化成日期格式
    |safe:转义  可以把css js等样式渲染到前端

views

def index(request):
    from datetime import datetime

    s= 'hello world dvdlej  vdnelegjn  nej  dje vnle vgjnlew ldeg gel eglkkeg '
    a= 12
    b= True
    ff = False
    file_size= 298355976576
    ddd= datetime.now()
    res= '<h1>你好啊</h1>'
    res1= '<script>alert(123)</script>'
    return render(request,'index.html',locals())

index.html

{#<p>过滤器  |左边的会当做过滤器的第一个参数 过滤器名右边的会当做过滤器的第二个参数</p>#}
{#<p>求数据长度:{{ s|length }}</p>#}
{#<p>加法运算:{{ n|add:10 }}、{{ s|add:13132 }}、{{ s|add:'DSB' }}</p>#}
{#<p>默认值(判断值是否为空):{{ b|default:'这个b布尔值是True' }}、{{ ff|default:'这个ff布尔值是Flase' }}</p>#}
{#<p>截取字符(截取5个字符 三个点也算):{{ s|truncatechars:8 }}</p>#}
{#<p>截取单词(截取8个单词 三个点不算):{{ ss|truncatewords:8 }}、{{ sss|truncatewords:4 }}</p>#}
{#<p>文件大小:{{ file_size|filesizeformat }}</p>#}
{#<p>切片操作:{{ s|slice:'0:2' }}、{{ s|slice:"0:8:2" }}</p>#}
{#<p>日期格式化:{{ ddd|date:'Y年/m月/d日' }}</p>#}
{#<p>转义:{{ res|safe }}、{{ res1 }}、后端直接标识安全:{{ res2 }}</p>#}

浏览器的显示结果

70

True、2222ff

he...

hello world dvdlej vdnelegjn nej dje vnle vgjnlew ...

277.9 GB

he

2020年/01月/07日

你好啊

前后端取消转义
前端
|safe
后端
from django.utils.safestring import mark_safe
mark_safe(‘

安全滴

‘)
总结:前端代码不一定非要在前端页面写,可以在后端写好传递给前端页面使用
这样的话 你就可以利用到后端更加多的逻辑语法
下面是举例
from django.utils.safestring import mark_safe
res2= mark_safe('<h1>积极阳光帅气</h1>')
    return render(request,'index.html',locals())

index.html
<p>{{ res2 }}</p>

三.模板语法逻辑相关

forloop 对象

判断for循环的开始结束的位置

索引 计数

如下是在html页面上

{# {% for foo in l %}#}
{#{{ forloop }}#}
{# {% endfor %}#}
    
    
    打印的结果是:
    {'parentloop': {}, 'counter0': 0, 'counter': 1, 'revcounter': 6, 'revcounter0': 5, 'first': True, 'last': False} {'parentloop': {}, 'counter0': 1, 'counter': 2, 'revcounter': 5, 'revcounter0': 4, 'first': False, 'last': False} {'parentloop': {}, 'counter0': 2, 'counter': 3, 'revcounter': 4, 'revcounter0': 3, 'first': False, 'last': False} {'parentloop': {}, 'counter0': 3, 'counter': 4, 'revcounter': 3, 'revcounter0': 2, 'first': False, 'last': False} {'parentloop': {}, 'counter0': 4, 'counter': 5, 'revcounter': 2, 'revcounter0': 1, 'first': False, 'last': False} {'parentloop': {}, 'counter0': 5, 'counter': 6, 'revcounter': 1, 'revcounter0': 0, 'first': False, 'last': True}
    
    ###第一个是True  最后一个是True

for 循环 if 判断

views.py 里面的是 l=[1,2,3,4,5,6]

html页面
{% for foo in l %}
{% if forloop.first %}
    <p>这是我的第一次</p>
    {% elif forloop.last %}
    <p>这个是最后一次</p>
    {% else %}
    <p>{{ foo }}</p>

{% endif %}

{% endfor %}

浏览器结果

这是我的第一次

2

3

4

5

这个是最后一次

如果是空的 可以用下面的empty来判断

views.py 里面的是 l=[]

html页面
{% for foo in l %}
{% if forloop.first %}
    <p>这是我的第一次</p>
    {% elif forloop.last %}
    <p>这个是最后一次</p>
    {% else %}
    <p>{{ foo }}</p>

{% endif %}
{% empty %} {# 这个是用来的判断的 如果容器内没有值#}
    <p>for循环的对象没有值</p>
{% endfor %}

四.对于多用和常用的可以起个别名

这个别名只能在with里面使用

views.py
def index(request):
d = {"username": 'jason', 'password': 123, 'hobby': ['read', {'username': ['jason', 'egon']}]}
return render(request,'index.html',{'l':l,'d':d} )


index.html
{% with d.hobby.1.username.1 as eg %}
    <p>别名{{ eg }}</p>
    
{% endwith %}

五.自定义的过滤器、标签 、inclusion_tag

自定义过滤器 标签 inclusion_tag
先完成以下前期准备工作
1.在应用名下新建一个名字必须叫templatetags文件夹
2.在该文件夹内新建一个任意名称的py文件(eg:mytag)
3.在该文件内 必须先写以下两句代码
from django.template import Library
register= Library()

总结 页面上使用他们 统一先导入

{% load mytag %}

mytag.py

from django.template import Library
register= Library()

#自定义的过滤器
@register.filter(name= 'my_sum')
def index(a,b):
    return a +b


#自定义的标签
@register.simple_tag(name= 'my_baby')
def index1(a,b,c,d):
    return '%s?%s?%s?%s?'%(a,b,c,d)


#自定义inclusion_tag
@register.inclusion_tag('demo.html',name='myin')
def index(n):
    l=[]
    for i in range(n):
        l.append(i)
    #将列表传递给demo.html ## 这个return给demo.html在上面@register这个里面
    return {'l':l}

index.html

<body>

<p>自定义的过滤器</p>
{% load mytag %}
<p>{{ 10|my_sum:90 }}</p>

{% if 10|my_sum:100 %}
    <p>条件成立</p>

{% endif %}
>>>>>>>>>>>>>>>>>>>>>>>
100

<p>自定义的标签</p>
{% load mytag %}
<p>{% my_baby 1 2 3 'hello world' %}</p>
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
1?2?3?hello world?

<p>自定义的inclusion_tag的使用</p>
{% load mytag %}
{% myin 5 %}
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
0
1
2
3
4

</body>
</html>

demo.html

<ul>
 {% for foo in l %}
 <li>{{ foo }}</li>
 {% endfor %}
  
</ul>

六.模板的继承

? 某一个页面大部分区域都是公用的 那这个页面就可以作为模板页面
? 当别人继承这个页面之后 如何修改对应的区域

先在模板页面上通过block实现划定区域
{% block content %} 
模板页面内容
{% endblock %}

子页面中先导入整个模板
{% extends '模板页面.html'%}
修改特定的区域  通过实现划定好的区域名称
{% block content %}
子页面内容
{% endblock %}

通常情况下 模板页面页面应该起码有三块区域
{% block css %} 
模板页面内容
{% endblock %}
{% block content %} 
模板页面内容
{% endblock %}
{% block js %}  
模板页面内容
{% endblock %}
# 模板的block块越多 可扩展性越高



还支持子页面调用父页面对应区域的内容 并且可以无限次调用
{{ block.super }}

urls.py

#模板的导入
    url(r'^mdzz/',views.mdzz),
    url(r'^loginn/',views.loginn),
    url(r'^register/',views.register)

views.py

def mdzz(request):    return render(request,'mdzz.html')def loginn(request):    return render(request,'loginn.html')def register(request):     return render(request,'register.html')

mdzz.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
    <link href="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">
    <script src="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/js/bootstrap.js"></script>
    {% block css %}

    {% endblock %}

</head>
<body>
<nav class="navbar navbar-inverse">
  <div class="container-fluid">
    <!-- Brand and toggle get grouped for better mobile display -->
    <div class="navbar-header">
      <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
        <span class="sr-only">Toggle navigation</span>
        <span class="icon-bar"></span>
        <span class="icon-bar"></span>
        <span class="icon-bar"></span>
      </button>
      <a class="navbar-brand" href="#">Brand</a>
    </div>

    <!-- Collect the nav links, forms, and other content for toggling -->
    <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
      <ul class="nav navbar-nav">
        <li class="active"><a href="#">Link <span class="sr-only">(current)</span></a></li>
        <li><a href="#">Link</a></li>
        <li class="dropdown">
          <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Dropdown <span class="caret"></span></a>
          <ul class="dropdown-menu">
            <li><a href="#">Action</a></li>
            <li><a href="#">Another action</a></li>
            <li><a href="#">Something else here</a></li>
            <li role="separator" class="divider"></li>
            <li><a href="#">Separated link</a></li>
            <li role="separator" class="divider"></li>
            <li><a href="#">One more separated link</a></li>
          </ul>
        </li>
      </ul>
      <form class="navbar-form navbar-left">
        <div class="form-group">
          <input type="text" class="form-control" placeholder="Search">
        </div>
        <button type="submit" class="btn btn-default">Submit</button>
      </form>
      <ul class="nav navbar-nav navbar-right">
        <li><a href="#">Link</a></li>
        <li class="dropdown">
          <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Dropdown <span class="caret"></span></a>
          <ul class="dropdown-menu">
            <li><a href="#">Action</a></li>
            <li><a href="#">Another action</a></li>
            <li><a href="#">Something else here</a></li>
            <li role="separator" class="divider"></li>
            <li><a href="#">Separated link</a></li>
          </ul>
        </li>
      </ul>
    </div><!-- /.navbar-collapse -->
  </div><!-- /.container-fluid -->
</nav>
<div class="container-fluid">
<div calss="row" >
    <div class="col-md-3" >
            <div class="list-group">
              <a href="/mdzz/" class="list-group-item active">###a标签
                首页
              </a>
              <a href="/register/" class="list-group-item">注册</a>###a标签
              <a href="/loginn/" class="list-group-item">登录</a>###a标签
              <a href="#" class="list-group-item">Porta ac consectetur ac</a>
              <a href="#" class="list-group-item">Vestibulum at eros</a>
</div>
    </div>
<div class="col-md-9">
            <div class="panel panel-primary">
          <div class="panel-heading">
            <h3 class="panel-title">Panel title</h3>
          </div>
          <div class="panel-body">
              {% block content %}
                     <div class="jumbotron">
              <h1>Hello, world!</h1>
              <p>...</p>
              <p><a class="btn btn-primary btn-lg" href="#" role="button">Learn more</a></p>
</div>
              {% endblock %}

          </div>
</div>
</div>
</div>
</div>

{% block js %}

{% endblock %}

</body>
</html>

loggin.html

{% extends 'mdzz.html' %}

{% block css %}
    <style>
    h2 {
        color:green;
    }
    </style>
{% endblock %}
{% block content %}
    {% include 'left.html' %}
    <h2 class="text-center">登录页面</h2>
    <form action="">
    <p>username:
        <input type="text" class="form-control">
    </p>
    <p>password:
        <input type="text" class="form-control" >
    </p>
        提交:<input type="submit " class="btn btn-success">

    </form>
    {{ block.super }}
{% endblock %}

{% block js %}
    <script>
    alert(123)
    </script>
{% endblock %}

register.html

{% extends 'mdzz.html' %}

{% block css %}
    <style>
    h2{
        color:red;
    }
    </style>
{% endblock %}

{% block content %}
<h2 class="text-center">注册页面</h2>
    <form action="">
    <p>username:
        <input type="text" class="form-control">
    </p>
    <p>password:
        <input type="text" class="form-control">

    </p>
    <p>
        <input type="submit" class="btn btn-danger">
    </p>
    </form>
{{ block.super }}
{{ block.super }}
{{ block.super }}
{% endblock %}

{% block js %}
    <script>
    alert(666)
    </script>
{% endblock %}

七.模板的导入

将html页面当做模块使用 哪里需要导哪里 这个html页面通常都不是完整的 只是一个局部样式
{% include ‘要导入的模块名‘ %}

举例

left.html

<p>这是我做的很美的一个模块</p>

将left.html模块导入到这个loginn.html中,直接在loginn.htm 要插入的位置放上{% include ‘left.html‘ %} 即可

八.基于django settings源码实现项目配置文件的 插拔式设计

conf.settings.py

NAME='我是暴露给用户的配置文件'

lib.conf.--init--.py

import importlib
import os
from lib.conf import global_settings
class Settings(object):
    def __init__(self):
        #先遍历出项目默认的全局匹配值的文件
        for  name in dir(global_settings):
            #判断变量名是否大写
            if name.isupper():
                #键值对设置对象
                k = name
                v= getattr(global_settings,name)
                setattr(self,k,v)

        #先获取暴露给用户的配置文件的字符串路径
        module_path = os.environ.get('xxx')
        #里面的importlib模块 导入到settings文件
        md= importlib.import_module(module_path)
        #md能拿到settings里面的所有的名字
        #同上操作
        for name in dir(md):
            #判断变量名是否大写
            if name.isupper():
                #键值对设置给对象
                k= name
                v= getattr(md,name)
                setattr(self,k,v)

settings = Settings()

lib.conf.global_settings.py

NAME ='我是项目默认的配置文件'

start.py

import os
import sys
BASE_DIR = os.path.dirname(__file__)
sys.path.append(BASE_DIR)

if __name__ == '__main__':
    #项目启动 就应该朝全局大字典中设置键值对
    os.environ['xxx']= 'conf.settings'
    from lib.conf import settings
    print(settings.NAME)

暴露给用户的配置文件,如果用户的存在 就用用户的, 如果用户的没有 ,就是用全局系统默认的

django其实有两个配置文件 一个是暴露给用户的可以自定义的配置 一个是项目默认的配置
        用户如果配置了就用用户的 没有配置就用默认的
        
        from django.conf import global_settings,settings
        
        settings = LazySettings()
        
        
        class LazySettings(...):
            def _setup(...):
                # 获取暴露给用户的配置文件字符串路径
                setting_module = os.environ.get(纯大写变量名)
                """
                manage.py
                os.environ.setdefault(纯大写变量名,'暴露给用户的配置文件字符串路径')
                """
                
                Settings(setting_module)
        def Settings(...)
            # 先遍历全局默认的配置文件       给对象设置键值对
            for setting in dir(global_settings):
                if setting.isupper():
                    setattr(self,setting,getattr(global_settings,setting))
                    
            
            # 再遍历暴露给用户的配置文件     给对象设置键值对
            md = importlib.import_module(setting_module)
            for setting in dir(md):
                if setting.isupper():
                    setattr(self,setting,getattr(md,setting))
            """
            利用的其实就是字典的键存在和不存在 下面语句的作用
            dict[key] = value
            """

相关推荐