zoukankan      html  css  js  c++  java
  • Django之模板层

    一. 前言

      Django模板层的知识包括标签,过滤器,自定义标签,自定义过滤器以及inclusion_tag,最重要的是模板的继承和导入,模板层最重要的是模板语法,之前我们涉及到的变量用模板语法{{}},涉及到逻辑用模板语法{% %},这里我们在追加几点,过滤器在模板语法{{ }}中写,而且只能传两个参数;标签在模板语法{% %}中写,且能传多个参数(参数之间用空格隔开).模板的继承和导入也是在模板语法{% %}中写.

      接下来我们回顾下后端朝前端传递数据的两种方式:

    from django.shortcuts import render
    
    # Create your views here.
    
    def login(request):
        '''模板语法只有2个:
        渲染变量:{{}} 1.深度查询--->>句点符;2.过滤器
        渲染标签:{% %}
        :param request:
        :return:
        '''
        name = "panshao"
        i = 10      #整型
        l = [1,2,3] #列表 
        info = {"name":"panshao", "age":22} #字典
        b = True    #布尔
        class Person(object):   
            def __init__(self, name, age):
                self.name = name
                self.age = age
        alex = Person("alex",33)  #对象
        egon = Person("egon",38)
    
        person_list = [alex, egon] 
    
        #return render(request, "login.html", {"name":name})
        return render(request, "login.html", locals()) #locals是局部变量的意思,这样就不用一个个去对应了;它会把这些局部变量直接传给模板,它传的时候就是按照{“name”:name} {"alex":alex}这种方式传的
    

      

    login.py

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        <h1>index</h1>
        <p>{{ name }}</p>
        <p>{{ i }}</p>
        <p>{{ info }}</p>
        <p>{{ l }}</p>
        <p>{{ alex }}</p>
        <p>{{ person_list }}</p>
        <p>{{ b }}</p>
        <hr>
        深度查询  是用 . 完成的 
        <p>{{ l.1 }}</p>     #我想要第2个元素
        <p>{{ info.name }}</p> #字典下的name那个键
        <p>{{ alex.age }}</p>  #alex这个变量对象
        <p>{{ person_list.1.age }}</p> #person_list中第二个人的年龄
    
    </body>
    </html>
    

      

      两种方法有利有弊,不过在之后我们会选用locals(),后端除了能向前端提交的Python的基本的数据类型: int, float, str, list, dict, tuple, set数据外,还能提交函数与类的对象,当我们传递函数名给前端时,会自动拿到该函数return的结果, 但是不支持传参,只支持传递无参函数.当传递类的对象obj给前端时,相当于print (obj),前端拿到的是该obj的内存地址,因为print(obj)走的是类的__str__()方法.所以传递类对象时,我们重新写__str__()能让前端拿到想要的内容. 前端想要获取后端传递过来的容器类型中的元素时,统一使用句点符(.):

    二. 过滤器

      过滤器在模板语法{{ }}中书写,过滤器最多支持传两个参数,(会把|左边的参数当做过滤器的第一个参数传进去),过滤器的基本语法: {{ 参数1|过滤器名字: 参数2}}, 有些过滤器没有参数2

      统计字符串长度{{ s|length}}: 会将s当做length的参数传进去,将s的长度打印出来

      获取的数据为空时就返回default后面定义的值{{ s|default: 's是空的字符串'}}, 这种方法跟后端的get方法很像,default必须要有两个参数

      将数字转化为表示文件大小的格式{{ file_size|filesizeformat}} 给file_size一串数字,会转化为多少兆,多少G之类的,如果file_size是204800,执行该过滤器后就是200kb

      格式化时间{{ ctime|date: 'Y-m-d'}}不需要和后端一样加% ('%Y-%m-%d'),后端代码为

    from datetime import datetime
        ctime = datetime.now()
    

      字符串的切片操作{{s|slice:'0: 8: 2'}},如果s='hello world',执行完该过滤器后是'hlow', slice后面的参数同python字符串切片参数一样,开头: 结尾: 步长,切片顾头不顾尾

      截取固定长度的字符串{{s|truncatechars:10}} 如果s='hello world' 执行完该过滤器后是'hello w...', 超出长度的部分会用...代替,当我们的参数为10时, 实际上截取的字符串长度为7,因为...占3位.

      按照空格截取文本内容{{s|truncatewords:2}}  如果s='he llo wor ld',执行完该过滤器后是:‘he llo ...’,截取至前两个空格,之后的内容用...表示。

      加法亦或是字符串拼接{{ n1|add:n2}}  如果n1=2, n2=4,那么结果为6。如果n1='hello', n2='world',那么结果为'helloworld'

       当我们后端向前端提交的字符串含有标签时,比如'<h1>this is title</h1>',为了防止脚本攻击(比如<script>while(1){alert('come on')}</script>),前端之后把你当成普通的字符串。当我们想要让前端帮我们执行提交的字符串中的标签内容时,有两种方式。

      1. 在前端通过{{字符串|safe}}告诉前端字符串很安全,可以大胆执行

      2. 后端用模块操作一下字符串,告诉前端我们给它的字符串很安全。

     
    from django.utils.safestring import mark_safe
    
    def login(request):
        html = reverse('login')
        s = '<h1>this is title</h1>'
        s = mark_safe(s)
        return render(request, 'login.html', locals())
    
    # 前端直接{{ s }}即可

    三. 标签

      标签在模板语法中{% %}书写, {% %}涉及到逻辑,标签一般是for循环,f判断以及它们的嵌套使用,除此之外还有empty标签。

      for 循环中可以使用forloop来给我们提供一些信息:

       for循环

    <!--l = [1, 2, 3, 4, 5]-->
    {% for foo in l %}
        <p>{{ foo }}</p>
        <p>{{ forloop }}</p>
    {% endfor %}
    

      

      if判断

    {% if flag %}
        <p>flag不为空</p>
        {% else %}
            <p>flag是空</p>
    {% endif %
    

      

      if与for嵌套使用

    {% for foo in s %}
        {% if forloop.first %}
            <p>这是第一次</p>
        {% elif forloop.last %}
            <p>这是最后一次</p>
        {% else %}
            <p>keep up</p>
        {% endif %}
    {% endfor %}
    

      

      empty

    {#{% for foo in '' %}#}
    {#    {% if forloop.first %}#}
    {#        <p>这是我的第一次</p>#}
    {#        {% elif forloop.last %}#}
    {#        <p>这是最后一次了啊</p>#}
    {#        {% else %}#}
    {#        <p>来啊来啊!!!</p>#}
    {#    {% endif %}#}
    {#    {% empty %}#}
    {#    <p>当for循环的对象为空的时候 会走empty</p>#}
    {#{% endfor %}#}
    

      

    四. 自定义inclusion_tag

      要自定义过滤器与标签,必须先做三件事

    1. 在应用文件夹下新建templatetags文件夹(必须叫这个名字)
    2. 在templatetags文件夹中新建一个py文件,名字任意,不过最好不要有中文 
    3. 在该py文件中固定写以下两句代码
      from django import template
      
      register = template.Library()

      自定义inclusion_tag

    from django import template
    
    register = template.Library()
    
    
    @register.inclusion_tag('login.html', name='login')
    def login(n):
        l = ['第%s项' % i for i in range(n)]
        return {'l': l}
    

      

    <!--login.html-->
    <ur>
        {% for foo in l %}
            <li>{{ foo }}</li>
        {% endfor %}
    </ur>
    

      在该例子中, 我们在前端调用inclusion_tag时:

    {% load my_tags %}
    {% login 5 %} 

      首先会将参数5传给login函数,函数执行完后的结果提交至login.html,然后将login.html的页面显示在调用该inclusion_tag的地方。

      inclusion_tag会将渲染过的login.html界面返回至调用它的位置,正是因为这种机制,所以它所渲染那个html页面中可以不需要head和body等各种标签,你需要返回什么就在里面写什么。

    五. 模板的继承

      1. 模板的继承

      首先需要被继承的模板中划分多个区域:

    {% block 给区域起的名字 %}
    
    {% endblock %}
    

      通常情况下一个模板至少需要三块区域:

    {% block css %}
        页面css代码块
    {% endblock %}
    
    {% block js %}
        页面js代码块
    {% endblock %}
    
    {% block content %}
        页面主体内容
    {% endblock %}
    

      子模板继承模板,首先要继承所有的内容:

    {% extends 'home.html' %}
    {#先继承home,必须写在首行,不然它不知道block是什么意思 跟include不一样,它有它自己独特的优势#}

      根据被block快的名字修改指定区域的内容

    {% block content %}
        <h1>登录页面</h1>
        <form action="">
            <p>username:<input type="text" class="form-control"></p>
        <p>password:<input type="text" class="form-control"></p>
        <input type="submit" class="btn btn-success">
        </form>
    {% endblock %}
    

      可以使用{{block.super}}使用父模板的该block的内容(使用该方法没有提示,要手撸)

    {% block content %}
        {{ block.super }}
    {% endblock %}
    

      注意:原模板中的block区域越多越好,因为越多代表可以修改的细节很多,扩展性就越强。继承后,子模板只能修改block区域中的内容。

      2. 静态文件配置

      当我们为了让路由名字改变时我们不需要修改HTML页面和视图函数中的内容,我们引入了反向解析。同理,为了防止settins.py文件夹中static文件夹的接口前缀改变而我们不需要html页面中head中script和link的接口前缀(需要修改的前提是他们导入的是static文件夹中的东西),我们引入了静态文件配置。

    {% load static %}  
        
    <link rel='stylesheet' href="{% static 'css/mycss.css'%}">  # 第一种方式
    <link rel='stylesheet' href="{% get_static_prefix %}css/mycss.css">  # 第二种方式
    

      

    生前无需久睡,死后自会长眠,努力解决生活中遇到的各种问题,不畏将来,勇敢面对,加油,你是最胖的,哈哈哈
  • 相关阅读:
    【leetcode】1534. 统计好三元组
    【leetcode】1351. 统计有序矩阵中的负数
    【leetcode】1523. 在区间范围内统计奇数数目
    【leetcode】204. 计数质数
    【leetcode】993. 二叉树的堂兄弟节点
    【leetcode】1598. 文件夹操作日志搜集器
    【leetcode】1389. 按既定顺序创建目标数组
    【leetcode】增减字符串匹配
    【leetcode】1185.一周中的第几天
    052-158
  • 原文地址:https://www.cnblogs.com/panshao51km-cn/p/11546207.html
Copyright © 2011-2022 走看看