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 }}
    
    从来就没有正确的选择,我们只不过是要努力奋斗,使当初的选择变得正确。
  • 相关阅读:
    Hessian简要入门
    MapReduce启动的Map/Reduce子任务简要分析
    hive默认分隔符引起的日志分割问题
    Spring MVC中发布Restful Web服务
    JPA基本介绍以及使用
    hsqldb简单使用总结
    Vim编辑器基本操作学习(二)
    locale错误导致Java中文乱码错误的总结
    Vim编辑器基本操作学习(一)
    hadoop map任务Combiner被调用的源码逻辑简要分析
  • 原文地址:https://www.cnblogs.com/gfeng/p/14564720.html
Copyright © 2011-2022 走看看