zoukankan      html  css  js  c++  java
  • 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之模板层

    模板语法

    只有两种书写格式

    1. {{ }}:变量相关
    2. {% %}:逻辑相关,列如:for,if

    模板语法之传值

    模板语法的传值适用于Python所有的数据类型,包括函数、类

    # views.py 下方所有模板语法的演示均参考index数据
    from django.shortcuts import render
    from datetime import datetime
    
    def index(request):
        # python基本数据类型
        i = 666
        f = 11.11
        s = '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 = True
        b1 = False
        ctime  = 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>
    

    模板语法之过滤器

    模板语法提供了一些内置方法,以助于快速的处理数据(过滤器最多只能有两个参数)

    过滤器:会自动将竖杠左侧的数据当做第一个参数:右侧的当做第二个参数

    # 类似于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_safe
        	sss1 = 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 template
      register = 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 }}
    
    从来就没有正确的选择,我们只不过是要努力奋斗,使当初的选择变得正确。
  • 相关阅读:
    Dot Net WinForm 控件开发 (七) 为属性提下拉式属性编辑器
    WinForm 程序的界面多语言切换
    c#遍历HashTable
    Dot Net WinForm 控件开发 (三) 自定义类型的属性需要自定义类型转换器
    Dot Net WinForm 控件开发 (六) 为属性提供弹出式编辑对话框
    Dot Net WinForm 控件开发 (一) 写一个最简单的控件
    Dot Net WinForm 控件开发 (四) 设置属性的默认值
    Dot Net WinForm 控件开发 (二) 给控件来点描述信息
    Dot Net WinForm 控件开发 (八) 调试控件的设计时行为
    Dot Net WinForm 控件开发 (五) 复杂属性的子属性
  • 原文地址:https://www.cnblogs.com/gfeng/p/14564720.html
Copyright © 2011-2022 走看看