django 之 视图层模板层
Posted bs2019
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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
看源码发现是绑定给类的方法
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
"""
以上是关于django 之 视图层模板层的主要内容,如果未能解决你的问题,请参考以下文章