• 05django模板层


    目的

    将页面的设计和Python的代码分离开会更干净简洁更容易维护

    核心内容

    • 变量 {{var_name}}
    • 标签 {% %}

    变量 {{ var_name }}

    1.变量的使用

    首先新建一个html5的页面

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    <p>{{ msg }}</p>
    <p>{{ dic }}</p>
    <p>{{ obj }}</p>
    <p>{{ li }}</p>
    </body>
    </html>
    

    在view中添加代码

    from django.shortcuts import render
    
    def test(request):
        # 传给模板的变量值可以是任意python类型,如下
        msg='hello world'
        dic={'k1':1,'k2':2}
        class Person(object):
            def __init__(self,name,age):
                self.name=name
                self.age=age
    
        obj=Person('egon',18)
        li = [1,'aaa',obj]
    
        return render(request,'test.html',{'msg':msg,'dic':dic,'obj':obj,'li':li})
        # 注意:
        # 1、render函数的第三个参数包含了要传给模板的变量值,是一个字典类型,该字典中的key必须与模板文件中的变量名相对应,
        #  render函数会去templates目录下找到模板文件,然后根据字典中的key对应到模板文件中的变量名进行赋值操作,最后将赋值后的模板文件内容返回给浏览器
        # 2、可以将render函数的第三个参数简写为locals(),如下
        return render(request,'test.html',locals()) #locals()会将函数test内定义的名字与值转换为字典中的k与v
    

    总结:

    Django模板中. 有特殊的意义

    list: 按list.index取值,注意不能用python原始取值方法list[0]
    
    取list中的第一个参数
    {{ list.0 }}
    
    取字典中key的值
    {{ d.name }}
    
    取对象的name属性
    {{ person_list.0.name }}
    
    .操作只能调用不带参数的方法
    {{ person_list.0.dream }}
    
    调用字符串对象的upper方法,注意不要加括号
    {{ msg.upper }}
    
    取对象的name属性
    {{ obj.name }}
    
    取列表的第2个元素,然后变成大写
    {{ li.1.upper }}
    
    取列表的第3个元素,并取该元素的age属性
    {{ li.2.age }}
    

    过滤器

    DJANGO模板自带了很多的过滤器,详细介绍:

    https://docs.djangoproject.com/zh-hans/2.2/ref/templates/builtins/

    语法

    {{obj|filter__name:param}}
    

    常用的过滤器

    default

      
    {{ value|default:"nothing"}}
    如果value值没传的话就显示nothing
    
    注:TEMPLATES的OPTIONS可以增加一个选项:string_if_invalid:'找不到',可以替代default的的作用。
    

    filesizeformat

    将值格式化为一个 “人类可读的” 文件尺寸 (例如 '13 KB', '4.1 MB', '102 bytes', 等等)。例如:
    
    {{ value|filesizeformat }}
    如果 value 是 123456789,输出将会是 117.7 MB。
    

    add

    给变量加参数
    
    {{ value|add:"2" }}
    value是数字4,则输出结果为6。
    
    {{ first|add:second }}
    如果first是 [1,.2,3] ,second是 [4,5,6] ,那输出结果是 [1,2,3,4,5,6] 。
    

    lower upper

    小写
    {{ value|lower }}
    
    大写
    {{ value|upper}}
    

    title

    标题
    
    {{ value|title }}
    

    ljust

    左对齐
    
    "{{ value|ljust:"10" }}"
    

    rjust

    右对齐
    
    "{{ value|rjust:"10" }}"
    

    center

    居中
    
    "{{ value|center:"15" }}"
    

    length

    {{ value|length }}
    
    返回value的长度,如 value=['a', 'b', 'c', 'd']的话,就显示4.
    

    slice

    切片
    
    {{value|slice:"2:-1"}}
    

    first

    取第一个元素
    
    {{ value|first }}
    

    last

    取最后一个元素
    
    {{ value|last }}
    

    join

    使用字符串拼接列表。同python的str.join(list)。
    
    {{ value|join:" // " }}
    

    truncatechars

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

    date

    日期格式化
    
    {{ value|date:"Y-m-d H:i:s"}}
    

    safe

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

    3.标签 {% %}

    3.1 for 标签

    #1、遍历每一个元素:
    {% for person in person_list %}
        <p>{{ person.name }}</p>
    {% endfor %}
    
    #2、可以利用{% for obj in list reversed %}反向循环。
    
    #3、遍历一个字典:
    {% for key,val in dic.items %}
        <p>{{ key }}:{{ val }}</p>
    {% endfor %}
    
    #4、循环序号可以通过{{ forloop }}显示 
    forloop.counter            当前循环的索引值(从1开始)
    forloop.counter0           当前循环的索引值(从0开始)
    forloop.revcounter         当前循环的倒序索引值(从1开始)
    forloop.revcounter0        当前循环的倒序索引值(从0开始)
    forloop.first              当前循环是第一次循环则返回True,否则返回False
    forloop.last               当前循环是最后一次循环则返回True,否则返回False
    forloop.parentloop         本层循环的外层循环
    
    #5、for标签可以带有一个可选的{% empty %} 从句,在变量person_list为空或者没有被找到时,则执行empty子句
    {% for person in person_list %}
        <p>{{ person.name }}</p>
    
    {% empty %}
        <p>sorry,no person here</p>
    {% endfor %}
    

    3.2 if 标签

    # 1、注意:
    {% if 条件 %}条件为真时if的子句才会生效,条件也可以是一个变量,if会对变量进行求值,
    在变量值为空、或者视图没有为其传值的情况下均为False
    
    # 2、具体语法
    {% if num > 100 or num < 0 %}
        <p>无效</p>
    {% elif num > 80 and num < 100 %}
        <p>优秀</p>
    {% else %}
        <p>凑活吧</p>
    {% endif %}
    
    #3、if语句支持 and 、or、==、>、<、!=、<=、>=、in、not in、is、is not判断。
    

    3.3 with 标签

    # with标签用来为一个复杂的变量名起别名,如果变量的值来自于数据库,
    # 在起别名后只需要使用别名即可,无需每次都向数据库发送请求来重新获取变量的值
    {% with li.1.upper as v %}
        {{ v }}
    {% endwith %}
    

    3.4 csrf_token 标签

    # 当用form表单提交POST请求时必须加上标签{% csrf_token%},该标签用于防止跨站伪造请求
    <form action="" method="POST">
        {% csrf_token %}
        <p>用户名:<input type="text" name="name"></p>
        <p>密码:<input type="password" name="pwd"></p>
        <p><input type="submit" value="提交"></p>
    </form>
    # 具体工作原理为:
    # 1、在GET请求到form表单时,标签{% csrf_token%}会被渲染成一个隐藏的input标签,
    #该标签包含了由服务端生成的一串随机字符串,如<input type="hidden" name="csrfmiddlewaretoken" value="dmje28mFo...OvnZ5">
    # 2、在使用form表单提交POST请求时,会提交上述随机字符串,服务端在接收到该POST请求时会对比该随机字符串,
    # 对比成功则处理该POST请求,否则拒绝,以此来确定客户端的身份
    

    3.5 注释标签

    # 单行注释
    {#   #}
    
    # 多行注释
    {% comment "Optional note" %}
        <p>Commented out text with {{ create_date|date:"c" }}</p>
    {% endcomment %}
    

    4. 自定义过滤器和标签

    1、在settings中的INSTALLED_APPS配置当前app,不然django无法找到自定义的simple_tag.

    2、在app中创建templatetags模块(模块名只能是templatetags)

    3、创建任意 .py 文件,如:my_tags.py

    #my_tags.py
    from django import template
    register = template.Library() # 注意变量名必须为register,不可改变
    
    #1、自定义过滤器
    @register.filter
    def my_multi_filter(v1 ,v2): # 自定义的过滤器只能定义最多两个参数,针对{{ value1 | filter_multi:value2 }},参数传递为v1=value1,v2=value2
        return  v1 * v2
    
    #2、自定义标签
    @register.simple_tag
    def my_multi_tag(v1, v2): # 自定义的标签可以定义多个参数
        return v1 * v2
    
    
    #3、自定义标签扩展之mark_safe
    # 注释:我们可以用内置的标签safe来让标签内容有语法意义,如果我们想让自定义标签处理的结果也有语法意义,
    # 则不能使用内置标签safe了,需要使用mark_safe,可以实现与内置标签safe同样的功能
    from django.utils.safestring import mark_safe
    
    @register.simple_tag
    def my_input_tag(id, name):
        res = "<input type='text' id='%s' name='%s' />" % (id, name)
        return mark_safe(res)
    

    4、在使用自定义simple_tag和filter的html文件中导入之前创建的 my_tags.py

    <!-- HTML在使用 -->
    
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    
    <!--必须先加载存有自定义过滤器和标签的文件-->
    {% load my_tags %}
    
    <!--salary的值为10,经过滤器my_multi_filter的处理结果为120-->
    {{ salary|my_multi_filter:12 }}
    
    <!--结果为2-->
    {% my_multi_tag 1 2 %}
    
    <!--
    结果为一个input标签,该表的属性id="inp1" name="username"
    注意:input的属性值均为字符串类型,所以my_input_tag后的两个值均为字符串类型
    -->
    {% my_input_tag "inp1" "username" %} 
    
    </body>
    </html>
    
    1. 在urls.py 和view.py 中 分布配置好才能生效
    对比
    #1、自定义过滤器只能传两个参数,而自定义标签却可以传多个参数
    
    #2、过滤器可以用于if判断,而标签不能
    {% if salary|my_multi_filter:12 > 200 %}
        <p>优秀</p>
    {% else %}
        <p>垃圾</p>
    {% endif %}
    

    模板的导入和继承

    1. include
    2. extends
    3. block
    母版:创建一个母版
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>
            {% block title %}自定义title名{% endblock %}
        </title>
    
        <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css"
              integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
        <style>
            * {
                margin: 0;
                padding: 0;
            }
    
            .header {
                height: 50px;
                 100%;
                background-color: #919191;
                margin-bottom: 20px;
            }
    
        </style>
    
    </head>
    <body>
    <div class="header"></div>
    
    <div class="container">
        <div class="row">
            <div class="col-md-3">
                <div class="list-group">
                    {% block sidebar %}
                        <a href="#" class="list-group-item active">服装城</a>
                        <a href="#" class="list-group-item">美妆馆</a>
                        <a href="#" class="list-group-item">超市</a>
                        <a href="#" class="list-group-item">全球购</a>
                        <a href="#" class="list-group-item">闪购</a>
                        <a href="#" class="list-group-item">团购</a>
                    {% endblock %}
    
                </div>
            </div>
    
            <div class="col-md-9">
                {% block content %}
                    base.html页面内容
                {% endblock %}
            </div>
        </div>
    
    </div>
    
    </body>
    </html>
    

    在base.html打上block 标签,实现母版的复用

    block
    {% extends "base.html" %}
    
    <!--用新内容完全覆盖了父模板内容-->
    {% block title %}
        index页面
    {% endblock %}
    
    
    {% block sidebar %}
        <!--该变量会将父模板中sidebar中原来的内容继承过来,然后我们可以在此基础上新增,否则就是纯粹地覆盖-->
        {{ block.super }}
    
        <!--在继承父模板内容的基础上新增的标签-->
        <a href="#" class="list-group-item">拍卖</a>
        <a href="#" class="list-group-item">金融</a>
    {% endblock %}
    
    {% block content %}
        <!--用新内容完全覆盖了父模板内容-->
        <p>index页面内容</p>
    {% endblock %}
    
    
    组件

    可以将常用的页面内容如导航条,页尾信息等组件保存在单独的文件中,然后在需要使用的地方按如下语法导入即可。

    {% include 'navbar.html' %}
    
    总结
    #1、标签extends必须放在首行,base.html中block越多可定制性越强
    
    #2、include仅仅只是完全引用其他模板文件,而extends却可以搭配block在引用的基础上进行扩写
    
    #3、变量{{ block.super }} 可以重用父类的内容,然后在父类基础上增加新内容,而不是完全覆盖
    
    #4、为了提升可读性,我们可以给标签{% endblock %} 起一个名字 。例如:
        {% block content %}
        ...
        {% endblock content %}  
    #5、在一个模版中不能出现重名的block标签。
    

    静态文件配置

    在setting.py 中进行配置
    STATIC_URL = '/static/' # 找到这一行,然后新增下述代码
    STATICFILES_DIRS = [
        os.path.join(BASE_DIR, 'statics'),# 获取静态文件在服务端的绝对路径
    ]
    #STATIC_URL = '/static/'就是为静态文件的绝对路径起了一个别名,以后我们只需要用路径/static/即可
    

    使用

    一般不建议直接使用静态路径

    static 的使用

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <!--注意:必须先加载文件static.py-->
        {% load static %}
        <!--注意:此处的static是一个定义在static.py中的一个标签,名字与文件名一样而已,不要搞混-->
        <link rel="stylesheet" href="{% static 'css/my.css' %}">
    </head>
    <body>
    <h4>我是红色的,点我就绿</h4>
    <img src="{% static 'img/rb.jpeg' %}" alt="">
    
    
    {% load static %}
    <script src="{% static 'js/jquery-3.3.1.min.js' %}"></script>
    <script src="{% static 'js/my.js' %}"></script>
    
    </body>
    </html>
    

    get_static_prefix 的使用

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <!--注意:同样需要先加载文件static.py-->
        {% load static %}
        <!--使用标签get_static_prefix拼接路径-->
        <link rel="stylesheet" href="{% get_static_prefix %}css/my.css">
    </head>
    <body>
    <h4>我是红色的,点我就绿</h4>
    <img src="{% get_static_prefix %}img/rb.jpeg" alt="">
    
    
    {% load static %}
    <script src="{% get_static_prefix %}js/jquery-3.3.1.min.js"></script>
    <script src="{% get_static_prefix %}js/my.js"></script>
    
    </body>
    </html>
    
  • 相关阅读:
    创建数据库命令(含自增id 创建时间 更新时间)
    jvm内存查看操作笔记
    dockerfile学习
    java 泛型
    IDE 改jvm内存大小 打印gc处理日志 jprofile内存分析工具使用和分析
    jvm内存(堆内存)了解
    vue 实现xmind 有空弄一下
    nmap接口扫描工具 有空了解下
    python 操作 redis
    Security 登录实现 这个博主的可以 亲测
  • 原文地址:https://www.cnblogs.com/slzhao/p/13234676.html
Copyright © 2020-2023  润新知