[Django框架之模板层]
django之settings源码
1.django其实有两个配置文件
-
一个是暴露给用户可以自定义的配置文件项目根目录下的settings.py
-
一个是项目默认的配置文件当用户不做任何配置的时候自动加载默认配置
# 默认全局配置文件,按住Ctrl键+鼠标左键点击可以进入查看from django.conf import global_settings
2.配置文件变量名必须是大写
其实它的内部有个监测机制,一旦识别是小写,会通过逻辑判断自动排除掉
疑问:为什么当用户配置了就使用用户配置的 不配置就是要默认的
# 如果在django项目下其他文件需要用到配置文件,采用下面方式导入# 既能拿到暴露给用户的配置,也能拿到全局的配置from django.conf import settings# 单例模式:按住Ctrl键+鼠标左键点击进入查看源码settings = LazySettings()os.environ.setdefault("DJANGO_SETTINGS_MODULE", "day05.settings") # 来自manage.py# settings源码ENVIRONMENT_VARIABLE = "DJANGO_SETTINGS_MODULE" # 通过manage.py获取键值对class LazySettings(LazyObject):def _setup(self, name=None):# os.environ看成是一个全局大字典 \'day05.settings\'settings_module = os.environ.get(ENVIRONMENT_VARIABLE)self._wrapped = Settings(settings_module) # Settings(\'day05.settings\')class Settings(object):def __init__(self, settings_module): # \'day05.settings\'for setting in dir(global_settings): # 获取全局配置文件里面所有的变量名if setting.isupper(): # 校验是否是纯大写setattr(self, setting, getattr(global_settings, setting))# 给Settings对象添加全局配置文件中所有的配置信息self.SETTINGS_MODULE = settings_module # \'day05.settings\'mod = importlib.import_module(self.SETTINGS_MODULE)# from day05 import settings # 导入暴露给用户的自定义配置文件for setting in dir(mod):if setting.isupper():setting_value = getattr(mod, setting)setattr(self, setting, setting_value)
Django之模板层
模板语法
只有两种书写格式
- {{ }}:变量相关
- {% %}:逻辑相关,列如:for,if
模板语法之传值
模板语法的传值适用于Python所有的数据类型,包括函数、类
# views.py 下方所有模板语法的演示均参考index数据from django.shortcuts import renderfrom datetime import datetimedef index(request):# python基本数据类型i = 666f = 11.11s = \'hello world jason egon justin kevin oscar\'l = [111,222,333,444]d = {\'username\':\'jason\',\'password\':123,\'hobby\':[\'read\',\'study\',\'run\',{\'username\':\'jason666\'}]}t = (111,222,333)se = {111,222,333}b = Trueb1 = Falsectime = datetime.today()file_size = 25113366# 传值方式1:利用字典挨个传值return render(request,\'index.html\',{\'i\':i,\'f\':f,\'s\':s})# 传值方式2:简单粗暴 locals()将当前名称空间中所有的变量名全部传递给页面return render(request,\'index.html\',locals())"""传值方式1 传值精确 不会造成资源浪费[\'xcvb/\']传值方式2 传值粗糙 可能会造成一定的资源浪费ps:为了演示方便 后面就都是用locals()"""补充:给HTML页面传递函数名和类名都会自动加括号调用(模板语法不支持额外的传参)
模板语法之获取值
前端获取后端传过来的容器类型的内部元素 统一采用句点符(.) 其实就是
\'\'\'django模板语法取值只能采用句点符(.) \'\'\'索引 键都可以无限制的点点点<p>{{ d.hobby.3.username }}</p><p>{{ l.0 }}</p> # 索引也是点~ 点点点 就ok
模板语法之过滤器
模板语法提供了一些内置方法,以助于快速的处理数据(过滤器最多只能有两个参数)
过滤器:会自动将竖杠左侧的数据当做第一个参数:右侧的当做第二个参数
# 类似于python的内置方法# 下面的内容,第一行是在前端的代码,第二行是运行的结果<p>统计长度:{{ s|length }}</p># 统计长度:41<p>加法运算:{{ i|add:100000000000 }}</p># 加法运算:100000000666<p>字符串拼接:{{ s|add:\'heiheihei\' }}</p># 字符串拼接:hello world jason egon justin kevin oscarheiheihei<p>字符串的切片操作:{{ s|slice:\'0:8\' }}</p># 字符串的切片操作:hello wo<p>日期格式:{{ ctime|date:\'Y年-m月-d日 H时:i分:s秒\' }}</p># 日期格式:2021年-03月-18日 17时:24分:35秒<p>默认值:左侧对应有值拿左侧:{{ b|default:\'哈哈\' }}</p># 默认值:左侧对应有值拿左侧:True<p>默认值:左侧对应没有值拿右侧{{ b1|default:\'哈哈\' }}</p># 默认值:左侧对应没有值拿右侧:哈哈<p>将数字格式化成表示文件大小的单位::{{ file_size|filesizeformat }}</p># 将数字格式化成表示文件大小的单位:23.9 MB<p>截取文本六个字符(三个点也算):{{ s|truncatechars:6 }}</p># 截取文本六个字符(三个点也算):hel...<p>截取文本(按照空格截取,三个点不算):{{ s|truncatewords:3 }}</p># 截取文本(按照空格截取,三个点不算):hello world jason ...<p>标签默认不做渲染:{{ h }}</p># 标签默认不做渲染:<h1>困了吗?</h1><p>{{ h|safe }}</p># 前端做渲染:困了吗?<p>{{ sss }}</p># <script>alert(123)</script><p>{{ sss|safe }}</p># 弹窗出现(模拟脚本攻击)<p>{{ sss1 }}</p># 后端做渲染# (知识点)转义:防止脚本攻击的出现前端|safe # 告诉前端这个数据是安全的后端h = "<h1>前端做渲染:困了吗?</h1>"sss = "<script>alert(123)</script>"from django.utils.safestring import mark_safesss1 = mark_safe(\'<h2>后端做渲染</h2>\')# mark_safe 标记安全ps:前端代码也可以在后端写好传入!!!
模板语法之标签(流程控制)
类似于python的流程控制
{{}} 变量相关(引用变量值){%%} 逻辑相关(流程控制 模块方法)# if 判断{% if b1 %}<p>有值</p>{% else %}<p>无值</p>{% endif %}# for循环:{% for foo in l %}<p>{{ foo }}</p><p>{{ forloop }}</p>{% endfor %}"""forloop内置对象:运行结果解析\'counter0\':从0开始技计数\'counter\': 从1开始计数\'first\': True,判断循环的开始\'last\': True:判断循环的结束"""# 嵌套使用:{% for foo in s %}{% if forloop.first %}<p>这是我的第一次~~</p>{% elif forloop.last %}<p>这是最后一次了啊~</p>{% else %}<p>{{ foo }}</p>{% endif %}{% empty %}<p>传入的数据是空的,没法儿for循环啊</p>{% endfor %}"""解释一波:forloop.first:判断本次循环是不是第一次,是,就执行下面的代码forloop.last: 判断是不是最后一次,是,就执行下面代码empty:当你的for循环对象为空的时候会自动走empty代码块的内容"""# 了解{% with d.hobby.3.username as name %}{{ name }}{{ d.hobby.3.username }}{% endwith %}"""运行结果:jason666 jason666可以通过as后面的别名快速的使用到前面非常复杂获取数据的方式取别名后原来的名字也能正常使用命名的范围:只能在with代码块儿的范围之内才能使用别名"""
自定义过滤器、标签、inclusion_tag
自定义过滤器、标签、inclusion_tag必须要有以下三步准备:
-
1.在应用下创建一个名字“必须”叫"templatetags"文件夹
-
2.在上述文件夹内创建一个任意名称的py文件,eg:mytag.py
-
3.在该py文件内“必须”固定先书写以下两句话
from django import templateregister = template.Library()
准备好后就可以开始定义
- 必须用register来自定义过滤器和标签,inclusion_tag,
- 注意register不能写错
自定义过滤器filter
需要先在html页面上加载 通过{% load 文件名 %}
# 跟默认的过滤器一样 最多只能接受两个参数@register.filter(name=\'myfilter\') # register进行.filter方法(过滤器取名)def index(a,b):# 简单的加法运算return a + b# 前端使用index.html:{% load mytag %}<p>{{ i|myfilter:100 }}</p># 渲染结果:766
自定义标签simple_tag
# 参数可以有多个@register.simple_tag(name=\'mysimple\')def index1(a,b,c,d):return \'%s - %s | %s - %s\'%(a,b,c,d)# 前端使用index.html渲染:{% load mytag %}{% mysimple 1 \'jason\' 222 \'egon\' %}# 渲染结果:1 - jason | 222 - egon
自定义inclusion_tag
内部原理
- 先定义一个方法
- 在页面上调用这个方法,并且可以传值
- 该方法会生成一些数据然后传递给一个html页面
- 之后将渲染好的结果放到调用的位置
inclusion_tag 应用场景:当html页面某个区域需要反复使用并且数据不是固定的
@register.inclusion_tag(\'login.html\',name=\'my_inclusion_tag\')def func2(n):l = []for i in range(1,n+1):l.append(\'第%s页\'%i)return locals() # 将当前局部名称空间的所有名字传给login.html页面# login.html小页面专门生成无序列表<ul>{% for foo in l %}<li>{{ foo }}</li>{% endfor %}</ul># 前端使用index.html展示渲染效果:{% my_inclusion_tag 4 %}{% my_inclusion_tag 2 %}# 渲染结果第1页第2页第3页第4页第1页第2页
模板的导入
# 类似于后端导模块 想要什么局部页面直接导入即可{% include \'myform.html\' %}
模板的继承
你需要事先在你想要使用的主页面上划定区域做好标记,之后在子页面继承的时候你就可以使用在主页面划定的区域,也就意味着,如果你不划定任何区域,那么你子页面将无法修改主页面内容
- 先在你想要继承的主页面上通过bolck划定你将来可能要改的区域,并做好标记
- 在子页面上线继承extends,利用block自动提示选取你想要修改的内容区域标记名称
- 在子页面extends中写你要修改主页面标记区的代码
- 然后就可以让子页面的修改内容渲染到主页面的划定区域上
先使用block划定区域母版{% block 区域标记名称 %}{% endblock %}子版{% extends \'home.html\' %}{% block 区域标记名称 %}{% endblock %}母版在划定区域的时候一般都应该有三个区域css区域html文档区域js区域ps:目的是为了让子版具有独立的css js等 增加扩展性{% block css %}{% endblock %}{% block content %}{% endblock %}{% block js %}{% endblock %}ps:子版也可以继续使用母版划定区域内的内容{{ block.super }}