django之模板語法


1. 變量

Django 模板中遍歷復雜數據結構的關鍵是句點字符

句點符

views.py

def index(request):
    '''
    模板語法:
    渲染變量 -> {{}}
        1. 深度查詢,用的句點符
        2. 過濾器
    渲染標簽 -> {% %}
    :param request:
    :return:
    '''
    name = 'edward'
    i = 10
    l = [111, 222, 333]
    info = {'name': 'yuan', 'age': 22}
    b = True

    class Person:
        def __init__(self, name, age):
            self.name = name
            self.age = age

    edward = Person('edward', 28)
    egon = Person('egon', 33)

    person_list = [edward, egon]

    return render(request, 'index.html', locals())  # 按'name'=name這種形式傳進去的

 

index.html

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


<h1>index</h1>

<p>{{ name }}</p>

<p>{{ i }}</p>

<p>{{ b }}</p>

<p>{{ info }}</p>

<p>{{ alex }}</p>

<p>{{ person_list }}</p>

<hr>

<strong>深度查詢</strong>
<p>{{ l.1 }}</p>
<p>{{ info.name }}</p>
<p>{{ edward.age }}</p>
<p>{{ person_list.0.name }}</p>

</body>
</html>

 

過濾器

{{obj|filter__name:param}}

default

如果一個變量是false或者為空,使用給定的默認值。否則,使用變量的值。例如:

{{ value|default:"nothing"}}

length

返回值的長度。它對字符串和列表都起作用。例如:

{{ value|length }}

如果 value 是 ['a', 'b', 'c', 'd'],那么輸出是 4。

filesizeformat

將值格式化為一個 “人類可讀的” 文件尺寸 (例如 '13 KB', '4.1 MB', '102 bytes', 等等)。例如:

 

{{ value|filesizeformat }}

如果 value 是 123456789,輸出將會是 117.7 MB

date

如果 value=datetime.datetime.now()

{{ value|date:``"Y-m-d"}}

slice

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

truncatechars

如果字符串字符多於指定的字符數量,那么會被截斷。截斷的字符串將以可翻譯的省略號序列(“...”)結尾。

參數:要截斷的字符數

 

例如:

{{ value|truncatechars:9}}

truncatewords

按單詞截斷

upper、lower

轉大寫和轉小寫

safe

Django的模板中會對HTML標簽和JS等語法標簽進行自動轉義,這樣是為了安全,防止xss攻擊。如果不想用轉義,就使用safe。

 

2. 標簽

標簽比變量更加復雜:一些在輸出中創建文本,一些通過循環或邏輯來控制流程,一些加載其后的變量將使用到的額外信息到模版中。一些標簽需要開始和結束標簽 (例如{% tag %} ...標簽 內容 ... {% endtag %})。

for標簽

遍歷每一個元素:

{% for person in person_list %}
    <p>{{ person.name }}</p>
{% endfor %}

可以利用{% for obj in list reversed %}反向完成循環。

遍歷一個字典:

{% for key,val in dic.items %}
    <p>{{ key }}:{{ val }}</p>
{% endfor %}

注:循環序號可以通過{{forloop}}顯示

{% for person in person_list %}
    <p>{{ forloop.counter }} {{ person.name }},{{ person.age }}</p>  <!-- counter0從0開始 -->
{% endfor %}

 

for empty 標簽

for標簽帶有一個可選的{% empty %} 從句,以便在給出的組是空的或者沒有被找到時,可以有所操作。

{% for person in person_list %}
    <p>{{ person.name }}</p>

{% empty %}
    <p>sorry,no person here</p>
{% endfor %}

 

if 標簽

{% if %}會對一個變量求值,如果它的值是“True”(存在、不為空、且不是boolean類型的false值),對應的內容塊會輸出。

{% if num > 100 or num < 0 %}
    <p>無效</p>
{% elif num > 80 and num < 100 %}
    <p>優秀</p>
{% else %}
    <p>湊活吧</p>
{% endif %}

 

with 標簽

使用一個簡單地名字緩存一個復雜的變量,當你需要使用一個“昂貴的”方法(比如訪問數據庫)很多次的時候是非常有用的

例如:

{% with business.employees.count as total %}
    {{ total }} employee{{ total|pluralize }}
{% endwith %}

 

csrf_token

這個標簽用於跨站請求偽造保護

<form action="" method="post">
    {% csrf_token %}
    name <input type="text" name="user">
    pwd <input type="text" name="pwd">
    <input type="submit">
</form>

 

3. 自定義標簽與過濾器

1、在settings中的INSTALLED_APPS注冊當前app,不然django無法找到自定義的simple_tag.

2、在app中創建templatetags模塊(模塊名只能是templatetags)

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

from django import template

register = template.Library()  # 只能叫register


# 最多傳兩個參數

@register.filter  # multi_filer = register.filter(multi_filer)
def multi_filter(x, y):
    return x * y


# 可以傳任意多的參數
@register.simple_tag()
def multi_tag(x, y,z,v):
    return x * y * z * v

 

4、在使用自定義simple_tag和filter的html文件中導入之前創建的 my_tags.py

{% load my_tags %}

 

5、使用simple_tag和filter(如何調用)

{% load my_tags %}
<h3>自定義過濾器</h3>

<!-- 自定義過濾器 -->
<p>{{ num_ten | multi_filter:20 }}</p>  <!-- 200 -->

<!-- 自定義標簽 -->

<p>{% multi_tag 10 10 10 10 %}</p>  <!-- 10000 -->



<!-- 自定義過濾器可以用於if判斷,自定義標簽不能 -->

{% if num_ten|multi_filter:15 > 100 %}
    <p>100</p>
{% else %}
    <p>{{ num_ten }}</p>
{% endif %}

 

4. 模板繼承

模版繼承可以讓您創建一個基本的“骨架”模版,它包含站點中的全部元素,並且可以定義能夠被子模版覆蓋的 blocks 。

下面這個例子很清楚的說明了模板繼承

base.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    {% block title %}
        <title>base</title>  <!-- 如果擴寫了就是擴寫的,不擴寫就還是用base -->
    {% endblock %}
    <!-- 最新版本的 Bootstrap 核心 CSS 文件 -->
    <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 {
            width: 100%;
            height: 50px;
            background-color: #369;
        }
    </style>
</head>
<body>

<div class="header"></div>

<div class="container">
    <div class="row">
        <div class="col-md-3">
            {% include 'advertise.html' %}
        </div>
        <div class="col-md-9">
            {% block con %}
                <h4>content</h4>
            {% endblock %}
        </div>
    </div>
</div>


</body>
</html>

這個模版,我們把它叫作 base.html, 它定義了一個可以用於兩列排版頁面的簡單HTML骨架。“子模版”的工作是用它們的內容填充空的blocks。

在這個例子中, block 標簽定義了三個可以被子模版內容填充的block。 block 告訴模版引擎: 子模版可能會覆蓋掉模版中的這些位置。

 

advertise.html

<div class="advert">
    <div class="panel panel-danger">
        <div class="panel-heading">Panel heading without title</div>
        <div class="panel-body">
            Panel content
        </div>
    </div>

    <div class="panel panel-warning">
        <div class="panel-heading">
            <h3 class="panel-title">Panel title</h3>
        </div>
        <div class="panel-body">
            Panel content
        </div>
    </div>

    <div class="panel panel-primary">
        <div class="panel-heading">Panel heading without title</div>
        <div class="panel-body">
            Panel content
        </div>
    </div>
</div>

 

index.html

{% extends 'base.html' %}

{% block title %}
    <title>index</title>
{% endblock %}


{% block con %}
    <div class="col-md-9">
        <h3>index</h3>

        <p>{{ name }}</p>

        <p>{{ i }}</p>

        <p>{{ b }}</p>

        <p>{{ info }}</p>

        <p>{{ alex }}</p>

        <p>{{ person_list }}</p>

        <hr>

        <strong>深度查詢</strong>
        <p>{{ l.1 }}</p>
        <p>{{ info.name }}</p>
        <p>{{ edward.age }}</p>
        <p>{{ person_list.0.name }}</p>


        <h3>過濾器</h3>

        <p>{{ now | date:"Y-m-d" }}</p>

        <p>{{ empty_list | default:"數據為空" }}</p>

        <p>{{ file_size | filesizeformat }}</p>

        <p>{{ text | truncatechars:9 }}</p>  <!-- 按字符截 -->

        <p>{{ text | truncatewords:10 }}</p>  <!-- 按單詞截 -->

        <p>{{ link | safe }}</p>  <!-- 告訴django正常渲染就行,不用防止xss攻擊 -->

        <hr>


        <h3>for 標簽</h3>

        {% for i in l %}
            <p>{{ i }}</p>
        {% endfor %}


        {% for i in info %}
            <p>{{ i }}</p>
        {% endfor %}

        {% for person in person_list %}
            <p>{{ person.name }},{{ person.age }}</p>
        {% endfor %}


        {% for person in person_list %}
            <p>{{ forloop.counter }} {{ person.name }},{{ person.age }}</p>
        {% endfor %}


        {% load my_tags %}
        <h3>自定義過濾器</h3>

        <!-- 自定義過濾器 -->
        <p>{{ num_ten | multi_filter:20 }}</p>  <!-- 200 -->

        <!-- 自定義標簽 -->

        <p>{% multi_tag 10 10 10 10 %}</p>  <!-- 10000 -->


        <!-- 自定義過濾器可以用於if判斷,自定義標簽不能 -->

        {% if num_ten|multi_filter:15 > 100 %}
            <p>100</p>
        {% else %}
            <p>{{ num_ten }}</p>
        {% endif %}
    </div>

{% endblock %}

 

orders.html

{% extends 'base.html' %}]


{% block title %}
    <title>orders</title>
{% endblock %}


{% block con %}
    {{ block.super }}  <!-- 既保留base的,又保留擴寫的 -->
    <h4>訂單</h4>
{% endblock con %}  <!-- 可以加名字,增加可讀性 -->

 

需要注意的是:

  • 如果你在模版中使用 {% extends %} 標簽,它必須是模版中的第一個標簽。其他的任何情況下,模版繼承都將無法工作。

  • 在base模版中設置越多的 {% block %} 標簽越好。請記住,子模版不必定義全部父模版中的blocks,所以,你可以在大多數blocks中填充合理的默認內容,然后,只定義你需要的那一個。多一點鈎子總比少一點好。

  • 如果你發現你自己在大量的模版中復制內容,那可能意味着你應該把內容移動到父模版中的一個 {% block %} 中。

  • If you need to get the content of the block from the parent template, the {{ block.super }} variable will do the trick. This is useful if you want to add to the contents of a parent block instead of completely overriding it. Data inserted using {{ block.super }} will not be automatically escaped (see the next section), since it was already escaped, if necessary, in the parent template.

  • 為了更好的可讀性,你也可以給你的 {% endblock %} 標簽一個 名字

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM