• 模板相关操作


    1. MVC框架和MTV框架

    1. MVC框架

        MVC,全名是Model View Controller,是软件工程中的一种软件架构模式,把软件系统分为三个基本部分:模型(Model)、视图(View)和控制器(Controller),具有耦合性低、重用性高、生命周期成本低等优点。
    ​      M: model 模型 操作数据库
    ​      V: view 视图 展示页面 HTML
    ​      C: controller 控制器 调度 业务逻辑
    

    2. MTV框架

    Model(模型):负责业务对象与数据库的对象(ORM)
    Template(模版):负责如何把页面展示给用户
    View(视图):负责业务逻辑,并在适当的时候调用Model和Template
    此外,Django还有一个urls分发器,它的作用是将一个个URL的页面请求分发给不同的view处理,view再调用相应的Model和Template
    

    2. 语法

    ​ 模板渲染的官方文档

      关于模板渲染你只需要记两种特殊符号(语法):

      {{ }}和 {% %}

      变量相关的用{{}},逻辑相关的用{%%}。

    3. 变量

    1. 万能的点调用

    {{ 变量名 }}

    变量名由字母数字和下划线组成。

    点(.)在模板语言中有特殊的含义,用来获取对象的相应属性值。

    举例说明

    views.py

    from django.shortcuts import render
    import datetime
    
    def index(request):
    
        name = "水手"
        num = 100
        lst = [1, 2, "aa", "bb"]
        dic = {"xx": "oo", "xxx": "ooo"}
        date = datetime.date(1993, 5, 2)  # 日期对象
    
        class Person():
            n = "黑哥"
    
            def p(self):
                return "床前明月光"
    
        obj = Person()
        return render(request, "index.html", {"name": name, "num": num, "lst": lst, "dic": dic,"date":date, "obj": obj})
        # print(locals()) 获得全局字典,传的数据多,效率低
        # return render(request, "index.html", locals())
    

    index.html 代码

        <h1>24期官网</h1>
        <h2>{{ name }}</h2>    # 获得后端name的值渲染到页面
        <h2>{{ num }}</h2>     # 获得后端num的值渲染到页面
        <h2>{{ lst }}</h2>     # 获得后端lst的值渲染到页面
        <h2>{{ dic }}</h2>     # 获得后端dic的值渲染到页面
        <h2>{{ obj }}</h2>     # 获得后端obj的对象渲染到页面
        <h2>{{ lst.1 }}</h2>   # {#点索引获取对应的值#}
        <h2>{{ dic.xx }}</h2>   # {#点键获取字典的值#}
        <h2>{{ obj.n }}</h2>    # {#点属性获取值#}
        <h2>{{ obj.p }}</h2>    # {#点方法获取返回值,前端调用不加括号#}
        <h2>{{ dic.keys }}</h2> {#先查找字典中的键,有此键就不调用方法了#}
        <h2>{{ dic.items }}</h2>  # {#点方法获取字典的键值对#}
        						# {# dic.values获取值,dic.keys获取键 #}
    

    2. 查询顺序

      字典查询(Dictionary lookup)
      属性或方法查询(Attribute or method lookup)
      数字索引查询(Numeric index lookup)

    举例说明

    dic = {"xx": "oo", "xxx": "ooo","keys":"我在执行我"}
    <h2>{{ dic.keys }}</h2> # 前端执行时先在字典中查询此键,有键就不执行字典的方法了
    # 结果是: 我在执行我 而不是: dict_keys(['xx', 'xxx']) 键的列表
    

    3. 注意点

    1. 调用方法不支持传参数
    2. 如果使用的变量不存在, 模版系统将插入 string_if_invalid 选项的值, 它被默认设置为'' (空字符串)

    4. 过滤器 filter

    作用:修改变量的显示结果

    1. 语法

    {{ value|filter_name }} # filter_name 过滤器名称

    {{ value|filter_name:参数 }}

    2. 具体举例

    1. default 默认

    注意:':'左右没有空格没有空格没有空格,nothing需要引号引起来

    <h2>{{ age|default:"Nothing" }}</h2>     
    # 变量不存在,显示为空字符串/none时,都会调用default默认值
    返回同样是nothing的还有有这个变量,但是值是False,空字典等值为空的
    

    注:TEMPLATES的OPTIONS可以增加一个选项:string_if_invalid:'找不到',可以替代default的的作用

    见上述做修改部分替代default的作用
    在settings文件中TEMPLATES的'OPTIONS'字典中再添加一个键值对 "string_if_invalid":"不存在或为空" 为空时或不存在时执行
    

    2. filesizeformat

    将值格式化为一个 “人类可读的” 文件格式大小 (例如 '13 KB', '4.1 MB', '102 bytes', 等等)

    {{ value|filesizeformat }}   #如果 value 是 123456789,输出将会是 117.7 MB
    {{ 1024|filesizeformat }}  # 1.0kb
    

    3. add 添加

    用于数字的加减,字符串拼接,列表相加等

    <h2>{{ num|add:22 }}</h2>    #  html语法加不加引号效果相同
    <h2>{{ num|add:"22" }}</h2>  #  html语法加不加引号效果相同 num=100  结果:122
        <h2>{{ lst|add:lst }}</h2> # 
        <h2>{{ name|add:"bsb" }}</h2> # 也可以用于字符串和列表等的相加
    

    4. widthratio 实现加减乘除

    <h2>{{ num|add:10 }}</h2>           #等同于   num+10
    <h2>{{ num|add:-10 }}</h2>          #等同于   num-10
    <h2>{% widthratio num 1 5 %}</h2>   #等同于   num/1*5
    <h2>{% widthratio num 5 1 %}</h2>   #等同于   num/5*1    必须3个参数  格式 参数1/参数2*参数3
    <h2>{% widthratio 10 5 2 %}</h2>    #等同于   10/5*2=4
    

    5. length 长度

    <h2>{{ name|length }}</h2>  # 字符长度
    <h2>{{ lst|length }}</h2>   # 列表长度
    <h2>{{ dic|length }}</h2>   # 字典长度
    <h2>{{ name|add:"bsb"|length }}</h2>  # 多重操作
    

    6. slice 切片

    <h2>{{ name|add:"abcdefg"|slice:"2:-1:2" }}</h2>  # ace  支持切片和步长
    

    7. first 取第一个值

    <h2>{{ name|first }}</h2>  # 获取第一个值
    <h2>{{ value|last }}</h2>  # 获取最后一个值      
    

    8. join 拼接

    <h2>{{ name|join:"//" }}</h2>  # 结果 水//手 相当于字符串拼接
    <h2>{{ dic|join:"//" }}</h2>   # 键拼接  xx//xxx
    <h2>{{ lst|join:"//" }}</h2>   # 迭代拼接 1//2//aa//bb
    

    9. truncatechars

    如果字符串字符多于指定的字符数量,那么会被截断。截断的字符串将以可翻译的省略号序列(“...”)结尾

    <h2>{{ "abcdefghigk"|truncatechars:3 }}</h2>  #  ...    保留几个字符,小于三也是三个点
    <h2>{{ "abcdefghigk"|truncatechars:6 }}</h2>  # abc...  保留6个,有三个点
    

    10. date日期格式化

    date = datetime.date(1993, 5, 2)  # 日期对象
    now = datetime.datetime.now()     # 现在时间
    
    <h2>{{ date|date:"Y-m-d"}}</h2>   #
    <h2>{{ now|date:"Y-m-d H:i:s"}}</h2> #  设置显示格式
    

    扩展,不过滤,在设置settings中修改

    # USE_L10N = True
    USE_L10N = False
    
    DATETIME_FORMAT = "Y-m-d H:i:s"
    DATE_FORMAT = "Y-m-d"
    TIME_FORMAT = "H:i:s"
    
    <h2>{{ date }}</h2>   #
    <h2>{{ now }}</h2> #  设置显示格式
    

    11. lower 小写

    <h2>{{ "NAme"|lower }}</h2>   # 全部小写   name
    

    12. upper 大写

    <h2>{{ "NAme"|upper }}</h2>   # 全部大写   NAME
    

    13. title 标题,首字母大写

    <h2>{{ "woShiShui"|title }}</h2> # 首字母大写  Woshishui
    

    14. safe 告诉django不需要转义

    ​ Django的模板中会对HTML标签和JS等语法标签进行自动转义,原因显而易见,这样是为了安全。但是有的时候我们可能不希望这些HTML元素被转义,比如我们做一个内容管理系统,后台添加的文章中是经过修饰的,这些修饰可能是通过一个类似于FCKeditor编辑加注了HTML修饰符的文本,如果自动转义的话显示的就是保护HTML标签的源文件。为了在Django中关闭HTML的自动转义有两种方式,如果是一个单独的变量我们可以通过过滤器“|safe”的方式告诉Django这段代码是安全的不必转义。

    # 语法:{{ value|safe }}
    'jjss':'<script> for (var i=0 ;i<5;i++){alert("123")}</script>'
            {{ jjss|safe }} # 告诉浏览器这是安全的代码
            {{ jjss }} # Django这个代码当做字符串处理 <script> for (var i=0 ;i<5;i++){alert("123")}</script>
            
        # 或者使用mark_save()方法
        from django.utils.safestring import mark_safe
        'jjss':mark_safe('<script> for (var i=0 ;i<5;i++){alert("123")}</script>')
    
    bd = '<a href="http://www.baidu.com">百度</a>' # 后端
    
    前端:
        <h2>{{ bd }}</h2>     # 显示字符串 <a href="http://www.baidu.com">百度</a>
        <h2>{{ bd|safe }}</h2> # 设置safe,显示为a标签 百度
    

    通过自定义标签,实现网址

    from django import template
    
    register = template.Library()
    
    @register.filter
    def show_a(v1,v2):
    
        return f'<a href="http://{v1}">{v2}</a>'
    
    {% load my_tags %}
    {{ 'www.baidu.com'|show_a:'百度'|safe }}
    # 第二种方法 
    # index函数传 a = "www.taobao.com" 通过 render{"a":a}传到前端,前段通过{{ a|show_a:'百度'|safe }}传参到自定义标签
    # 第三种方法
    @register.filter(is_safe=True)  #不能使用index传参
    def show_a(v1,v2):
    
        return f'<a href="http://{v1}">{v2}</a>'
    {% load my_tags %}
    {{ 'www.baidu.com'|show_a:'百度' }}
    # 第四种方法
    导入一个模块 mark_safe,用mark_safe将返回的结果包起来
    from django.utils.safestring import mark_safe
    @register.filter
    def show_a(v1,v2):
    
        return mark_safe(f'<a href="http://{v1}">{v2}</a>')
    #return mark_safe('<a href="http://{}">{}</a>'.format(v1,v2)) 传参
    

    15. truncatewords

    msg = "我 是 i love you my baby"
    
    <h3>{{ msg|truncatewords:2 }}</h3> # {#  以空格区分截断,不是字符字节  #} 我 是 ...
    <h3>{{ msg|truncatechars:2 }}</h3> # 注意二者的区分  ...
    

    16. divisibleby 是否整除

    <h1>{{ 10|divisibleby:2 }}</h1>   # True
    <h1>{{ 10|divisibleby:3 }}</h1>   # False
    

    5. 自定义过滤器

    1. 自定义过滤器

    1.在app下创建一个名叫templatetags的包 (templatetags名字不能改)

    2.在包内创建py文件 (文件名可自定义 my_tags.py)

    3.在my_tags.py中写代码:

    from django import template
    register = template.Library()  # register名字不能错,固定
    

    4. 写上一个函数 + 加装饰器

    @register.filter
    def xx(v1,v2):
        ret = v1+v2
        return ret.upper()
    

    5. 使用

    index.html 中

    {% load my_tags %}   # 加载py文件
    {{ "alex"|xx:"dsb" }}  # alex和dsb 分别对应两个参数,渲染返回值
    					# 参数至多两个,至少一个   name = "alex"可以通过index函数传递
    

    6. 其他写法

    from django import template
    
    register = template.Library()
    
    @register.filter
    def xx(v1,v2="dsb"):
        ret = v1 + v2
        return ret.upper()
    
    {% load my_tags %}  # html文件调用,先加载py文件
    {{ "alex"|xx }}     # 后端添加默认参数,得到返回值  ALEXDSB
    

    只有一个参数

    from django import template
    
    register = template.Library()
    
    @register.filter
    def xx(v1):
        ret = v1
        return ret.upper()
    
    {% load my_tags %}
    {{ "alex"|xx }}     # 后端添加默认参数,得到返回值,页面展示  ALEX
    

    给函数起一个别名

    from django import template
    
    register = template.Library()
    
    @register.filter(name="xxsb")
    def xx(v1,v2):
        ret = v1 + v2
        return ret.upper()
    
    {% load my_tags %}
    {{ "alex"|xxsb:"dsb" }}   # 注意用别名xxsb,而不是xx  ALEXDSB
    

    6. 模板中的标签

    1. 语法{% tags %}

    2. for 循环标签

    1. for的一些参数

    {{ forloop.counter }}      循环的索引 从1开始
    {{ forloop.counter0 }}     循环的索引 从0开始
    {{ forloop.revcounter }}   循环的索引(倒叙) 到1结束
    {{ forloop.revcounter0 }}   循环的索引(倒叙) 到0结束
    {{ forloop.first }}        判断是否是第一次循环  是TRUE
    {{ forloop.last }}         判断是否是最后一次循环  是TRUE
    {{ forloop.parentloop }}   当前循环的外层循环的相关参数
    # forloop其实是一个字典,上边是通过.键取的值
    

    2. 举个栗子

    table = [[1,2,3],["a","b","c"],[7,8,9]]  # 后端传导前端
    
    # 使偶数行偶数列变红
    <table border="2">
        <tbody>
            {% for lst in table %}
                <tr>
                {% for foo in lst %}
                    <td style="{% if forloop.counter|divisibleby:2 and forloop.parentloop.counter|divisibleby:2 %}color: red{% endif %}">{{ forloop.counter }}{{ foo }}</td>
                {% endfor %}
                </tr>
            {% endfor %}
        </tbody>
    </table>
    

    3. for ... empty

    如果没有lst1时则显示empty的内容

        <ul>
            {% for i in lst1 %}
            <li>{{ i }}</li>
                {% empty %}
                <li>列表不存在</li>
            {% endfor %}
        </ul>
    

    3. if 条件标签

    {% if num > 100 or num < 0 %}
        <p>无效</p>  <!--不满足条件,不会生成这个标签-->
    {% elif num > 80 and num < 100 %}
        <p>优秀</p>
    {% else %}  <!--也是在if标签结构里面的-->
        <p>凑活吧</p>
    {% endif %}
    
    1. if语句支持 and 、or、==、>、<、!=、<=、>=、in、not in、is、is not判断,注意条件两边都有空格。
    2. if支持过滤器语法 {% if 10|add:2 %} {{ "成功" }} {% endif %}
    3. if 不支持算数运算 + - * / %
    4. 不支持连续判断 10 > 5 > 1 false 与Python不同,先判断10>5 的True,无法与1比较

    4. with 给变量起别名

    方法1
    {% with total=business.employees.count %}  #注意等号两边不能有空格
        {{ total }} <!--只能在with语句体内用-->
    {% endwith %}
    方法2
    {% with business.employees.count as total %}
        {{ total }}
    {% endwith %}   # 就是名字太长时节省写法,只能在with标签内使用
    

    7. {% csrf_token %} 防止跨站请求伪造

    <form action="" method="post">
        #  name="csrfmiddlewaretoken" 
        {% csrf_token %}    # 会添加一个隐藏的input框. 当提交数据是,协同csrf令牌一同提交. 
        <input type="text" name="name">
        <button>提交</button>
    </form>
    

    8. 模板和继承

    1. 模板继承(母版继承)

    1. 创建一个base.html页面(作为母版,其他页面来继承它使用)
    2. 在母版中定义block块(可以定义多个,整个页面任意位置)
    	{% block content %}  <!-- 预留的钩子,共其他需要继承它的html,自定义自己的内容 -->
    
    	{% endblock %}
    
    3 其他页面继承写法
    	{% extends 'base.html' %}  必须放在页面开头
    4 页面中写和母版中名字相同的block块,从而来显示自定义的内容
        {% block content %}  <!-- 预留的钩子,共其他需要继承它的html,自定义自己的内容 -->
            {{ block.super }}  #这是显示继承的母版中的content中的原内容
            这是xx1
        {% endblock %}
    

    2. 继承问题

    {% extends 'base.html' %} 必须放在页面开头

    1. 建base文件,可以命名多个block,不同名即可
    2. 想自定义自己继承后文件的属性,style要放在block中即可
    3. {{ block.super }} 继承父类,注意格式,双括号

    3. 组件

    网站 www.jq22.com

    1 创建html页面,里面写上自己封装的组件内容,title.html
    2 新的xx.html页面使用这个组件
    	{% include 'title.html' %}
    

    9. 静态文件

    1. 标签法

    # 引用静态文件      
        {% load static %}       # 自动寻找到static对应的静态资源.
        <link rel="stylesheet" href="{% static 'css/bootstrap.min.css' %}">
        <link rel="stylesheet" href="{% static 'css/dashboard.css' %}">
    
    # 引用js
        {% load static %}    # 自动寻找到static对应的静态资源.
        <script src="{% static "mytest.js" %}"></script> #'/static/mytest.js'
    
    # 多出引用同一个资源时, 可以重新命名.
        {% load static %}
        {% static "images/hi.jpg" as myphoto %}
        <img src="{{ myphoto }}"></img>
    

    2. 别名法

    <link rel="stylesheet" href="/static/css/dashboard.css">
    

    3. get_static_prefix

    {% load static %}   
    <link rel="stylesheet" href="{% get_static_prefix  %}css/dashboard.css">
    {% get_static_prefix  %} == /static/ 别名
    

    4. 静态文件配置

    1 项目目录下创建一个文件夹,例如名为jingtaiwenjianjia,将所有静态文件放到这个文件夹中
    2 settings配置文件中进行下面的配置
    	# 静态文件相关配置
        STATIC_URL = '/abc/'  #静态文件路径别名
    
        STATICFILES_DIRS = [
            os.path.join(BASE_DIR, 'jingtaiwenjianjia'),
        ]
    

    10. 自定义标签

    1. 自定义标签和过滤器

    1 在应用app01下创建一个叫做templatetags的包(名称不能改),在里面创建一个py文件,例如my_tags.py
    2 在my_tags.py文件中引用django提供的template类,写法
    	from django import template
    	#register名称不可变,library大写
    	register = template.Library()
    	
    	#自定义过滤器
        @register.filter   # 参数至多两个
        def xx(v1,v2):
            return v1+v2
    	#使用:
    		{% load my_tags %}   # 加载上文件名xxoo,相当于引入xxoo.py文件
    		{{ name|xx:'oo' }}  # xx是函数名 传两个参数
    	
    # 自定义标签 没有参数个数限制
    @register.simple_tag
    def num_my(*args,**kwargs):  # 给的参数没有限制
        return '_'.join(args) + "*".join(kwargs.values()) #返回的值是已经处理过的.
    #使用
        {% load my_tags %}
    	{% num_my "1" "2" "3" a="alex" b="taibai" %} # 注意返回值时join,可迭代,不能是数字,其他方法可以返回数字
    
        # inclusion_tag 返回html片段的标签
        @register.inclusion_tag('result.html')
        def res(n1): #n1 : ['aa','bb','cc']
    
            return {'li':n1 }
    	使用:
    		{% res a %}
    	
    

    2. 自定义标签和过滤器大前提

    1 在应用下创建一个叫做templatetags的文件夹(名称不能改),在里面创建一个py文件,例如my_tags.py
    
    2 在xx.py文件中引用django提供的template类,写法
    	from django import template
    	#register名称不可变,library大写
    	register = template.Library()
    

    3.自 定义过滤器执行流程

    1. 页面请求 127.0.0.1/new/
    2. 找到 url(r'^test/', views.test) 执行 test函数
    3. test有第三个参数,render{"name":"Alex"}传到test.html文件中
    4. {{ name|addoo:"dsb"}}加载my_tags.py文件,调用my_tags中的addoo函数
    5. 执行my_tags中的addoo函数 return n1+n2,参数一一对应
    6.替换test.html中内容,响应浏览器,显示结果
    

    4. 自定义标签执行流程

    1. 页面请求 127.0.0.1/new/
    2. 找到 url(r'^new/', views.new) 执行 new函数
    3. new有第三个参数,{"name":"Alex"}传到new.html文件中
    4. {% load xx %}加载xx.py文件,调用{% res name "dsb" %}函数
    5. 执行xx中的res函数 return n1+n2,参数一一对应
    6.替换new.html中内容,响应浏览器,显示结果
    

    5. inclusion_tag 返回html片段的标签执行流程

    1. 页面请求 127.0.0.1/new/
    2. 找到 url(r'^test/', views.test) 执行 test函数
    3. test有第三个参数,{"a":a}传到test.html文件中
    4. {% load xx %}加载xx.py文件,调用{% res a "s2" %}函数
    5. 执行xx中的res函数
    6. 将return值返回给@register.inclusion_tag("result.html")的result.html文件
    7. 修饰后依次跳回test.html文件,响应浏览器,显示结果
    

    11. 自定义过滤器和标签的区别

    1. 前者最多接受2个参数,后者没有限制      {% if 10|add:2 %}
    2. 前者可以在作为if的判断条件,后者不可以 不能识别
    

    12. 面试题

    cdn地址:https://www.bootcdn.cn/

       模板中使用{% sqr_list 3 %},生成如下的dropdown list 控件(下拉菜单)
        key    text
        1        1的平方是1
        2        2的平方是4
        3        3的平方是9
    
        请写出sqr_list的实现
    

    views.py

        from django.shortcuts import render
    
        def index(request):
    
            return render(request,"index.html")
    

    使用inclusion_tag标签

    在app应用中创建templatetags的my_tags.py

    from django import template
    register = template.Library()
    
    # 第一中方法,列表
    @register.inclusion_tag('dropdown_list.html')
    def sqr_list(num):
        data = [f'{i} ---{i}的平方是{i**2}' for i in range(1,num+1)]
        return {'data':data} # 传给showhome.html
    
    #第二种方法,字典
    @register.inclusion_tag('dropdown_list.html')
    def sqr_list(num):
        return {"i":{i:f'{i}的平方是{i**2}' for i in range(1,num+1)}}
    

    index.html

    {% load static %}
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <link rel="stylesheet" href="{% static 'bootstrap-3.3.7-dist/css/bootstrap.min.css' %}">
        {# <link href="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet"> #}
    </head>
    <body>
    	{% load my_tags %}  # 加载my_tags.py文件
    	{% sqr_list 10 %}    # 调用了my_tags文件,传参
        <script src="{% static 'jquery.js' %}"></script>
        <script src="{% static 'bootstrap-3.3.7-dist/js/bootstrap.min.js' %}"></script>
    
        {#<script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
    <script src="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script>#}
        {##}
    
    </body>
    </html>
    

    showhome.html

    # 第一种方法
    <div class="dropdown">
        <button class="btn btn-default dropdown-toggle" type="button" id="dropdownMenu2" data-toggle="dropdown"
                aria-haspopup="true" aria-expanded="false">
            key  text
            <span class="caret"></span>
        </button>
        <ul class="dropdown-menu" aria-labelledby="dropdownMenu2">
            {% for foo in data %}
                <li><a href="#">{{ foo }}</a></li>
            {% endfor %}
        </ul>
    </div>
    # 第二种方法
    <div class="dropdown">
        <button class="btn btn-default dropdown-toggle" type="button" id="dropdownMenu2" data-toggle="dropdown"
                aria-haspopup="true" aria-expanded="false">
            key  text
            <span class="caret"></span>
        </button>
        <ul class="dropdown-menu" aria-labelledby="dropdownMenu2">
            {% for k,v in i.items %}
                <li><a href="#">{{ k }}&nbsp;&nbsp;{{ v }}</a></li>
            {% endfor %}
        </ul>
    </div>
    
  • 相关阅读:
    Lombok 安装、入门
    Centos 6.5中使用yum安装jdk
    Mysql规范和使用注意点(转)
    Java编码规范
    windows2016重新配置sid
    Postman POST接口请求无法获取数据
    微信修改密码
    SQL事务
    .net时间格式化
    SQL查询列是否有重复值
  • 原文地址:https://www.cnblogs.com/lvweihe/p/11754647.html
Copyright © 2020-2023  润新知