十五 django-模板语法

一、概要

对于模版,其实就是读取模版(其中嵌套着模版标签),然后将模型中获取的数据插入到模版中,最后将信息返回给用户。

官方文档

二、模板应用

1、说明

只要是在html里面有模板语法就不是html文件了,这样的文件就叫做模板

本质就是html+模板语法

2、为什么要使用模板

  • 对页面设计进行的任何改变都必须对 Python 代码进行相应的修改。 网站设计的修改往往比底层 Python 代码的修改要频繁得多,因此如果可以在不进行 Python 代码修改的情况下变更设计,那将会方便得多。
  • Python 代码编写和 HTML 设计是两项不同的工作,大多数专业的网站开发环境都将他们分配给不同的人员(甚至不同部门)来完成。 设计者和HTML/CSS的编码人员不应该被要求去编辑Python的代码来完成他们的工作。
  • 程序员编写 Python代码和设计人员制作模板两项工作同时进行的效率是最高的,远胜于让一个人等待另一个人完成对某个既包含 Python又包含 HTML 的文件的编辑工作。

2、基本使用

  1. views.py
    class User:
        def __init__(self, name=None, age=0):
            self.name = name
            self.age = age
      # views      
     def index(request):
           title = "Hello Django"
           num = 110
           li = [1, 2, 3, 4, 5]
           dic = {'name': '小明', 'age': 20}
           user1 = User(name='小明')
           user2 = User(name='小红')
            user_list = [user1, user2]
           context = {
               'num': num,
               'title': title,
               'li': li,
               'dic': dic,
               'user': user1,
               'user_list': user_list,
           }
       return render(request, 'home/index.html', context)        
    
  2. templates/home/index.html
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <script src="/static/js/jquery-3.3.1.js"></script>
    </head>
    <body>
    <ul>
        <li>数字:{{ num }}</li>
        <li>字符串:{{ title }}</li>
        <li>列表:{{ li.0 }}</li>
        <li>列表:{{ li.1 }}</li>
        <li>列表:{{ li.2 }}</li>
        <li>字典:{{ dic.name }}</li>
        <li>字典:{{ dic.age }}</li>
        <li>对象:{{ user.name }}</li>
        <li>对象:{{ user.age }}</li>
        <li>列表:{{ user_list.1.name }}</li>
    </ul>
    <h3>遍历li的值</h3>
    {% for item in li %}
        <p>{{ item }}</p>
    {% endfor %}
    <h3>遍历列表,去对象的值</h3>
    {% for user in user_list %}
        用户名:<span>{{ user.name }}</span>
        密码:<span>{{ user.age }}</span>
    {% endfor %}
    <h3>遍历字典,</h3>
    {% for user in dic.items %}
        用户名:<span>{{ user.name }}</span>
        密码:<span>{{ user.age }}</span>
    {% endfor %}    
    <h3>遍历列表,去对象的值: 倒序</h3>
    {% for user in user_list reversed %}
        用户名:<span>{{ user.name }}</span>
        密码:<span>{{ user.age }}</span>
    {% endfor %}
    </body>
    </html>
    

三、模板语法

1、变量--{}

1.1、 {}语法

  1. 语法格式
    {{ }}
    
  2. 举个栗子
    #views.py
    def index(request):
      return render(request, 'home/index.html', {'content','模板语法'})
    
    <body>
     <p>{{ content }}</p>
    </body>
    

1.2、语法

  1. 语法格式
    对象.变量名
    
  2. 应用
    字典查询(Dictionary lookup)
    属性或方法查询(Attribute or method lookup)
    数字索引查询(Numeric index lookup)
    对象.方法名(必须无参)
    
  3. 举个栗子
    见基本

2、标签--{% tag %}

标签看起来像是这样的: {% tag %}。标签比变量更加复杂:一些在输出中创建文本,一些通过循环或逻辑来控制流程,一些加载其后的变量将使用到的额外信息到模版中。

一些标签需要开始和结束标签 (例如{% tag %} ...标签 内容 ... {% endtag %})

2.1、for

  1. 语法格式1
    {% for 元素 in 可迭代对象 %}
        {{ 元素 }}
    {% endfor %}
    {% for 元素 in 可迭代对象 %}
        {{ 元素. 属性}}
    {% endfor %}
    
  2. 语法格式2
    {% for 元素 in 可迭代对象 reversed%}
        {{ 元素. 属性}}
    {% endfor %}
    
  3. 语法格式3
    {% for 元素 in 可迭代对象 %}
        <p>{{元素.属性}}</p>
    {% empty %}
        <p>空元素</p>
    {% endfor %}
    
  4. 语法格式4
    {% for item in 可迭代对象 %}
     # 默认从1开始计数
        {{ forloop.counter }}
        # 表示从0开始计数
        {{ forloop.counter0 }}
        #
        {{ forloop.recounter }}
        {{ forloop.recounter0 }}
        # 判断是否是第一个元素
        {{ forloop.first }}: {{ item }}
        # 判断是否是最后一个元素
        {{ forloop.last }}: {{ item }}
    {% endfor %}
    
  5. 示例代码
    {% for item in li  %}
        <h3>计算器</h3>
        计数默认:<span>{{ forloop.counter0 }}</span>
        计数倒序:<span>{{ forloop.revcounter }}</span>
        是否第一项:<span>{{ forloop.first }}</span>
        是否是最后一项:<span>{{ forloop.last }}</span>
    {% endfor %}
    
    {% for link in links %}
        {{ link }}
        {% if not forloop.last %} | 
        {% endif %}
    {% endfor %}
    

2.2、if

  1. 语法格式
    {% if 条件表达式1 %}
    {% elif 条件表达式2  %}
    {% else %}
    {% endif %}
    
  2. 示例代码
    {% if num > 100 or num < 0 %}
        <p>无效</p>
    {% elif num > 80 and num < 100 %}
        <p>优秀</p>
    {% else %}
        <p>差</p>
    {% endif %}
    

2.3、csrf_token

  1. 说明
    用于生成csrf_token的标签,用于防治跨站攻击验证。注意如果你在view的index里用的是render_to_response方法,不会生效。其实,这里是会生成一个input标签,和其他表单标签一起提交给后台的。
    注意:在settings中的中间件MIDDLEWARE中配置打开
    'django.middleware.csrf.CsrfViewMiddleware',
  2. 语法格式
    {%csrf_token%}
    
  3. 示例代码
    <form action="{% url "bieming"%}" >
              <input type="text">
              <input type="submit"value="提交">
              {%csrf_token%}
    </form>
    

2.4、url

  1. 说明
    引用路由配置的地址
  2. 语法格式
    {% url 'name' %}
    
  3. 举个栗子
    url的用法也很简单,只要在urlpatterns里使用它,附加一个name
    urlpatterns = [
     url(r'^home$','index' ,name="test_url"),
    ]
    
    <a href="{% url 'test_url' %}"></a>
    

2.5、static

  1. 说明
    引用静态文件
  2. 使用步骤
    1、在首部使用模板标签{% load staticfiles %}来说明一下内容,将载入静态文件;
    2、使用{% static 'css/style.css' %}来指明CSS框架文件的存放位置;
    3、若html文件中,出现需要引用静态文件的地方,都需要用static来替换。
  3. 示例代码
    <!DOCTYPE html>
    <html lang="en">
    {% load staticfiles %}
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <link href="{% static 'css/common.css'%}" rel='stylesheet'>
        <script src="{% static 'js/jquery-3.3.1.js'%}"></script>
    </head>
    <body>
    </body>
    </html>
    

模板标签

  1. 说明
    该标签允许在(模板中)包含其它的模板的内容。 标签的参数是所要包含的模板名称,可以是一个变量,也可以是用单/双引号的字符串。 每当在多个模板中出现相同的代码时,就应该考虑是否要使用 {% include %} 来减少重复。
  2. 语法
    {% include '引入的模板名' %} 
    
  3. 示例代码
    top.html
    <div>
        <a href="{% url 'login' %}">请登录</a>
        <a href="{% url 'register' %}">免费注册</a>
    </div>
    
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
     {% include 'top.html' %}
    </body>
    </html>
    

3、过滤器 {{obj|filter__name:param}}

可以通过过滤器来修改变量的显示,过滤器的形式是:{{ variable | filter }},管道符号'|'代表使用过滤器
过滤器能够采用链式的方式使用,例如:{{ text | escape | linebreaks }}
过滤器还可以带参数,例如: {{ bio|truncatewords:30 }}
过滤器的参数中如果带有空格,那么需要用引号引起来,例如:{{ list | join : ", "}}
django中30个内建的过滤器

3.1、add

  1. 说明
    给变量加上相应的值
    过滤器首先会强制把两个值转换成Int类型。如果强制转换失败, 它会试图使用各种方式吧两个值相加。它会使用一些数据类型 (字符串, 列表, 等等.)
  2. 语法格式
     {{ value|add:"值" }} 
    
  3. 举个栗子
    #st = 'hello'
    {{ st|add:"world" }}
    

3.2、default

  1. 说明
    如果一个变量是False或者为空,使用给定的默认值。否则,使用变量的值
  2. 语法格式
    {{ value|default:",默认值" }}
    
  3. 举个栗子
    title = ''
    {{ title|default:",默认值" }}
    

3.3、length

  1. 说明
    返回值的长度。它对字符串和列表都起作用
  2. 语法格式
    {{ value|length }}
    
  3. 举个栗子
    li =  ['a', 'b', 'c', 'd']
    {{ li|length }}  #4
    

3.5、date

  1. 说明
    按指定的格式字符串参数格式化 date 或者 datetime 对象
  2. 语法格式
    {{ value|date:"日期格式" }}
    
  3. 举个栗子
    #如果 now_time = datetime.datetime.now()
    {{ now_time|date:"Y-m-d H:i:s" }}
    

4、自定过滤器

4.1、说明

在内置的方法满足不了我们的需求的时候,就需要自己定义属于自己的方法了,自定义方法分别分为filter和simple_tag

4.2 、区别

  1. 传参:
    • filter默认最多只支持2个参数:可以用{{value|fun:"p1, p1, p3" }}这种形式将参数传递个函数
    • simple_tag支持多个参数:{% fun p1 p2 p3 p4 %} 有多少就写多少
  2. 模板语言if条件:
  • filter支持if
      # 函数的结果作为if语句的条件
      {% if value|f1 %}   
         <h1>True</h1>
      {% else %}
         <h1>False</h1>
    
  • simple_tag: 不支持模板语言if条件`

4.3、步骤

  1. 在settings中的INSTALLED_APPS,注册app
  2. 在app中创建templatetags目录,目录名必须为templatetags
  3. 创建一个自定义的custom_tags.py
    from django import template
    from django.utils.safestring import mark_safe
    # register的名字是固定的,不可改变
    register = template.Library()
    # 过滤器
    @register.filter
    def test_filter(value, param):
        return value + param
    @register.filter
    def test_filter2(value, param1,param2):
        return value + param1 + param2
    # 标签
    @register.simple_tag
    def multi_tag(value, p2, p3, p1):
        return value * p2 * p3 * p1
    @register.simple_tag  # 标签
    def my_input(id, arg):
        result = "<input type='text' id='%s' class='%s' />" % (id, arg,)
        return mark_safe(result)
    
  4. 在使用自定义simple_tag和filter的html文件中导入之前创建的 custom_tags.py
  5. 在引用模板中导入:{% load custom_tags %}
  6. 在模板中使用
    {#  使用filter方式调用自定义方法  #}
    <!-- 将当做参数传递给test_filter1函数进行处理    处理方式 test_filter2(test_filter1) -->
    <p>{{ test_filter1|test_filter2}}</p>
    !-- 将test_filter当做参数传递给test_filter2函数进行处理,接受2个参数  处理方式
        <p>{{ test_filter1|test_filter2:"xxx" }}</p>
    {#  使用simple_tag方式调用自定义方法  #}
    <!-- 将k1当做参数传递给multi_tag函数进行处理,接收多个参数  处理方式 multi_tag("处理的值", "参数1" "参数2" "参数3") -->
    <p>{% multi_tag "处理的值" "参数1" "参数2" "参数3" %}</p>
    

四、模版继承

1、说明

Django模版引擎中最强大也是最复杂的部分就是模版继承了。模版继承可以让您创建一个基本的“骨架”模版,它包含您网站中的全部元素,并且可以定义能够被子模版覆盖的块

2、相关语法

  1. 继承语法
    {% extends "母版名称" %} 
    
  2. 块语法
    {% block 块名称 %}
      重写内容
    {% endblock %}
    

3、示例代码

  1. 母版
    <!DOCTYPE html>
    <html lang="en">
    {% load staticfiles %}
    <head>
        <meta charset="UTF-8">
        <title>
            {% block  page_title %}
            {% endblock %}
        </title>
        {% block page_css %}
        {% endblock %}
        {% block page_jq %}
        {% endblock %}
    </head>
    <body>
    <div>
        <div id="head">
            {% block page_head %}
            {% endblock %}
        </div>
        <div id="content">
            {% block page_content %}
            {% endblock %}
        </div>
        <div id="footer">
            {% block page_footer %}
            {% endblock %}
        </div>
    </div>
    </body>
    </html>
    
  2. 子模板
    {% extends 'base.html' %}
    {% block page_jq %}
     jq代码
    {% endblock %}
    {% block page_head %}
     头部HTML代码
    {% endblock %}
    {% block page_content %}
     主体HTML内容代码
    {% endblock %}
    {% block page_footer %}
     底部HTML内容代码
    {% endblock %}
    

4、总结

  1. 如果你在模版中使用 {% extends %} 标签,它必须是模版中的第一个标签。其他的任何情况下,模版继承都将无法工作。
  2. 在base模版中设置越多的 {% block %} 标签越好。请记住,子模版不必定义全部父模版中的blocks,所以,你可以在大多数blocks中填充合理的默认内容,然后,只定义你需要的那一个。多一点钩子总比少一点好。
  3. 如果你发现你自己在大量的模版中复制内容,那可能意味着你应该把内容移动到父模版中的一个 {% block %} 中。
  4. 如果需要获取父模板中的block 的内容,可以使用{{ block.super }} 变量。如果你想要在父block 中新增内容而不是完全覆盖它,它将非常有用。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,222评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,455评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,720评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,568评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,696评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,879评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,028评论 3 409
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,773评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,220评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,550评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,697评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,360评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,002评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,782评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,010评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,433评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,587评论 2 350