3 - django-template模板基本使用

1 Template

        使用 Django的 模板系統 (Template System)來實現將Python代碼和HTML代碼分開的目的。
python的模板包涵:HTML代碼+邏輯控制代碼 , 將具體數據嵌入到前端模板的語法,在一個html文件中包含模板語法的文件,能夠認爲是模板文件前端

1.1 模板的基礎使用

主要分爲兩部分:渲染變量使用雙大括號{{ }},渲染標籤則使用雙大括號雙百分號{% %}python

1.1.1 變量

在html頁面中使用兩個大括號包起來的字符串叫作變量:shell

{{ Var_name }}

這裏經過python django的shell環境來舉例(在這個環境中能夠直接引用 所屬django模塊中的變量等信息)django

# 使用 manage.py進入shell界面
終端中輸入:python manage.py shell
 
>>> from django.template import Context,Template
>>> t = Template('My name is {{ name }}')
>>> c = Context({'name':'dachenzi'})
>>> t.render(c)        # render會把變量進行渲染
'My name is dachenzi'
>>>

1.1.2 註釋標籤

單行註釋 {# #}
多行註釋 {% comment %} ... {% endcomment %}.後端

{# 這是一個註釋 #}
{% comment %}
這是多行註釋
{% endcomment %}.

1.1.3 深度查詢

若是傳遞的變量是屬組或者字典,那麼須要進行深度查詢(經過使用.(點)來完成深度查詢):app

{{ Var_Name.username }}    # 獲取Var_Name中的key爲:username的值 --> 變量爲字典類型
{{ Var_Name.2 }}      # 獲取Var_Name中第2個值 --> 變量爲list類型

使用.帶進行深度查詢,查詢list類型的數據框架

>>> from django.template import context,Template
>>> t = Template('hello {{ name.1}}')
>>> c = Context({'name':[1,2,3]})
>>> t.render(c)
'hello 2'

使用items循環字典類型(不加括號)函數

{% for key,value in user_dict.items %}
<li>{{  key }}-{{ value }}</li>
{% endfor %}

1.1.4 內置變量過濾器filter

        能夠理解爲python中的內置函數,過濾器是模板的特有語法,經過前端來過濾部分數據。注意filter只能傳遞一個參數(也能夠說是兩個參數,由於第一個個參數已經固定,就是被處理的那個)。
格式:oop

{{ var|method:parameter}}

method表示過濾器部分過濾器以下:

過濾器 說明 舉例
first 取列表第一個元素
last 取列表最後元素
capfirst 首字母大寫
cut 從字符串中移除指定的字符 {{ 'aLbLcL'|cut:'L' }}答案是abc
yesno 變量能夠是True、False、None,yesno的參數
給定逗號分隔的三個值,返回3個值中的一個。
True對應第一個
False對應第二個
None對應第三個
若是參數只有2個,None等效False處理
{{ value | yesno:"yeah,no,maybe"}}
add 加法。參數是負數就是減法 數字加{{ value | add:"100"}}
列表合併{{mylist | add:newlist}}
divisibleby 可否被整除 {{ value | divisibleby:"3" }}能被3整除返回True
addslashes 在反斜槓、單引號或者雙引號前面加上反斜槓 {{ value | addslashes }}
length 返回變量的長度 {% if my_list | length > 1 %}
default 變量等價False則使用缺省值 {{ value | default:"nothing" }}
default_if_none 變量爲None使用缺省值 {{ value |default_if_none:"nothing" }}
date 格式化 date 或者 datetime 對象 實例:{{my_dict.date|date:'Y n j'}}
Y 2000 年
n 1~12 月
j 1~31 日
切片相關 {{ value7|filesizeformat }}文件的字節數
{{ value7|first }}第一個字符
{{ value7|length }}長度
{{ value7|slice:":-1" }}切片

1.1.5 自定義過濾器之filter

        內置的過濾器總有不能知足咱們業務需求的時候,這時,咱們能夠自定義過濾器,官方文檔:https://docs.djangoproject.com/zh-hans/2.0/howto/custom-template-tags/

具體步驟爲:

  1. app目錄下建立templatetags包(名稱必須爲templatetags)
  2. 在包下建立任意 .py 文件,如:my_tags.py ,用來存放自定義的filter或tag函數
  3. 編寫自定義過濾器
  4. 在模板中加載templatetags並調用

下面是my_tags.py的文件內容

from django import template # 須要先導入文件
 
register = template.Library() # register的名字是固定的,不可改變,由於下面會進行調用
 
@register.filter # 註冊
def multi(num1,num2):
return num1 * num2

在引用的html模板文件中進行加載(能夠放在模板文件頭部,或者用以前加載也能夠,當和extend同時使用時,放在entend下面)

{% load my_tags %} # 這裏的名字就是咱們建立的my_tags.py的文件名

調用

{{ hello|multi:2 }}    # hello 表示傳遞的第一個參數,2表示傳遞的是第二個參數,冒號後面必需要緊跟傳遞的參數,多一個空格都不行

PS:filter 的函數只能接受一個額外參數(兩個參數,默認會把要處理的對象看成第一個參數,第二個參數是咱們須要傳遞的參數),能夠用於if/for等語句的條件,渲染時 使用 {{ 參數1 | xxx:參數2 }} 渲染 。

1.1.6 自定義過濾器之simple_tag

simpletag與filter不一樣的是,能夠接受多個參數,但不能夠用if/for等語句的條件,使用 {% xxx %} 渲染,建立步驟與filter相同

編寫simpletag

# my_tags.py文件

from django import template # 須要先導入文件
 
register = template.Library() # register的名字是固定的,不可改變,由於下面會進行調用

@register.simple_tag   # 必需要裝飾咱們自定義的函數才行
def simple_tag_multi(num1,num2):
return num1 * num2 

加載完畢後調用方式使用 {% %}

{% simple_tag_multi 10 20 %}  # 參數以空格隔開,多個空格效果相同

1.2 邏輯控制語法

循環等邏輯語句須要使用{% %} 來進行渲染

1.2.1 for標籤

{% for i in li %}  # li 爲後端傳遞給模板的變量
<p>{{ i }}</p>
{% endfor %}       #使用endfor來表示循環結束

在for循環中存在一個forloop變量,該變量記錄循環相關數據

  • forloop.counter:表示當前迭代數(第幾回循環)從1開始
  • forloop.counter0:同上,可是從0開始
  • forloop.first:判斷這次循環是不是第一次循環,是則返回True
  • forloop.revcounter:表示當前迭代數(第幾回循環)- 倒序
  • forloop.last:判斷這次循環是不是最後一次循環
  • forloop.parentloop:用於在嵌套循環時,獲取父循環的上面的信息

reversed和empty:

  • reversed:對可迭代對象進行逆序
  • empty:若是可迭代對象爲空
{% for athlete in athlete_list reversed %}
...
{% empty %}
... 若是被迭代的列表是空的或者不存在,執行empty
{% endfor %}

1.2.2 if標籤

{% if li.1 > 100 %}
<p> 大於 </p>
{% elif li.1 < 100 %}
<p> 小於 </p>
{% else %}
<p> 等於 </p>
{% endif %}         #使用endif來表示條件判斷結束

1.2.3 ifequal/ifnotequal 標籤

{% ifequal %} 標籤比較兩個值,當他們相等時,顯示在 {% ifequal %} 和 {% endifequal %} 之中全部的值。
下面的例子比較兩個模板變量 user 和 currentuser :

{% ifequal user currentuser %}
 <h1>Welcome!</h1>
{% endifequal %}

和 {% if %} 相似, {% ifequal %} 支持可選的 {% else%} 標籤

{% ifequal section 'sitenews' %}
 <h1>Site News</h1>
{% else %}
 <h1>No News Here</h1>
{% endifequal %}

1.3 特殊標籤

{% url 'varname' %}:引用路由配置的地址

<form action="{% url "LOGIN"%}" method="POST">    # 路由引用
          <input type="text">
          <input type="submit" value="提交">
</form>

{% verbatim %}:禁止render解析。

既在有的時候咱們僅僅只是想打印出 {{ hello }} 而已,使用verbatim來禁止render進行解析

{% verbatim %}
    {{  hello }}
{% endverbatim %}
 
# 使用verbatim 包起來的代碼 將不會進行解析

{% csrf_token %}:用於跨站請求僞造保護,防止跨站攻擊的。

<form>
{% csrf_token %}
</form>

通常用在form表單中。

1.4 extends模板繼承

        到目前爲止,咱們的模板範例都只是些零星的 HTML 片斷,但在實際應用中,你將用 Django 模板系統來建立整個 HTML 頁面。 這就帶來一個常見的 Web 開發問題: 在整個網站中,如何減小共用頁面區域(好比站點導航)所引發的重複和冗餘代碼?Django 解決此類問題的首選方法是使用一種優雅的策略 —— 模板繼承.
        本質上來講,模板繼承就是先構造一個基礎框架模板,然後在其子模板中對它所包含站點公用部分和定義塊進行重載.

編寫模板須要使用模板標籤:
        {% block name%} {% endblock %}:全部的 {% block %} 標籤告訴模板引擎,子模板能夠重載這些部分。 每一個{% block %}標籤所要作的是告訴模板引擎,該模板下的這一塊內容將有可能被子模板覆蓋。

下面是一個html模板文件:

// index.html文件

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>

</head>
<body>

    <div class="title"></div>
    <div class="left">
        <div class="left_list">
            <a href="/booklist/">文章列表</a>
        </div>

    </div>
    <div class="right">
        {% block content %}   // 這裏定義content,表示這裏能夠被繼承模板進行替換
        {% endblock %}    // 包起來的表示代碼段
    </div>

</body>
</html>

HTML中包含 block 語句塊的均可以稱爲模板文件

        子模板進行繼承,並定製本身要顯示的內容(子模板不須要額外的html代碼,其代碼都來自於模板文件),僅僅須要定義 block塊內的信息便可,固然也能夠不定義,或者在block塊中調用父模板的內容。

// test.html

{% extends 'index.html' %}   // 繼承模板文件
 
{% block  content %}     // 針對模板中content的代碼塊進行定義

    <h1>hello world</h1>
    <h1>hello world</h1>
    <h1>hello world</h1>
    <h1>hello world</h1>
    <h1>hello world</h1>
    <h1>hello world</h1>
 
{% endblock %}

使用注意:

  • 若是在模板中使用 {% extends %} ,必須保證其爲模板中的第一個模板標記(html首部)。 不然,模板繼承將不起做用。
  • 通常來講,基礎模板中的 {% block %} 標籤越多越好。 記住,子模板沒必要定義父模板中全部的代碼塊,所以你能夠用合理的缺省值對一些代碼塊進行填充,而後只對子模板所需的代碼塊進行(重)定義。 俗話說,鉤子越多越好。
  • 若是發覺本身在多個模板之間拷貝代碼,你應該考慮將該代碼段放置到父模板的某個 {% block %} 中。若是你須要訪問父模板中的塊的內容,使用 {{ block.super }} 這個標籤吧,這一個魔法變量將會表現出父模板中的內容。 若是隻想在上級代碼塊基礎上添加內容,而不是所有重載,該變量就顯得很是有用了。
  • 不容許在同一個模板中定義多個同名的 {% block %} .存在這樣的限制是由於block 標籤的工做方式是雙向的。也就是說,block 標籤不只挖了一個要填的坑,也定義了在父模板中這個坑所填充的內容。若是模板中出現了兩個相同名稱的 {% block %} 標籤,父模板將無從得知要使用哪一個塊的內容。
  • 一個html文件只能引入一個模版

1.5 include引入

        在不少網站中,基本上的都會有一個開頭和一個結尾,在每個網頁中都會顯示。相對於這種的來講,在Django中,最好的方法就是使用include的標籤,在每個模板中都加入這個開頭和結尾的標籤。
        簡單來講,就是那些多個頁面都須要的公共標籤放在一個統一的html文件,供其餘html文件引入。

{% include 'tpl.html' %}  : 表示引入tpl.html文件。

看下面的例子:

# -------------------- tpl.html --------------------
<div>
    <h1>hello world</h1>
</div>
 
 
 
 
# -------------------- xxx.html --------------------
 
...
 
    <div>
        {% include 'tpl.html' %}   
        {% include 'tpl.html' %}  // tpl.html的所有內容會在這裏填充
        ...
    </div>   
 
...

在一個頁面中能夠經過include引入不一樣的公共組件。

相關文章
相關標籤/搜索