Django模板系統

 

 

 

 

 

官方文檔css


經常使用語法

Django模板中只須要記兩種特殊符號:html

{{  }}和 {% %}python

{{ }}表示變量,在模板渲染的時候替換成值,{% %}(表示標籤)表示邏輯相關的操做。數據庫

變量

{{ 變量名 }}django

變量名由字母數字和下劃線組成。bootstrap

點(.)在模板語言中有特殊的含義,用來獲取對象的相應屬性值。瀏覽器

幾個例子:安全

view中代碼:服務器

複製代碼
def template_test(request):
li = [11, 22, 33]
dic = {"name": "mcw"}

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

def dream(self):
return "{} is dream...".format(self.name)

ma = Person(name="ma", age=18)
hong = Person(name="hong", age=9000)
ming = Person(name="ming", age=18)

person_list = [ma,hong,ming]
return render(request, "template_test.html", {"li": li, "dic": dic, "person_list": person_list}) #傳字符串,數字,列表,字典等
複製代碼

模板中支持的寫法:app

複製代碼
<p>
取li中的第一個參數 :<br>
{{ li.0 }} <br> {# 列表.索引,而不是列表[索引] #}
取字典中key的值: <br>
{{ dic.name }} <br> {# 字典.鍵 而不是字典['鍵'] #}
取對象的name屬性(對象變量),能夠連着取 :<br>
{{ person_list.0.name }} <br> {# person_list.0是ma對象,對象.name取實例變量 #}
操做只能調用不帶參數的方法 :<br>
{{ person_list.0.dream }}<br> {# person_list.0是ma 對象,對象.方法(而不是對象.方法())調用不帶參數的方法#}
</p>
複製代碼

 

 也能夠這樣多行傳遞並渲染:render拿到模板文件和變量並將模板文件替換而後發送給瀏覽器,是python作的渲染

字符串  數字 列表  字典

列表索引不能用負數取值,報錯:

取值:

字典中的值也能夠點下去,get方法不能用。類的返回值很差看,能夠用str方法

 取字典中的數據:支持keys values  items

 

注:當模板系統遇到一個(.)時,會按照以下的順序去查詢:

  1. 在字典中查詢
  2. 屬性或者方法
  3. 數字索引

如今字典中找,而不是先使用keys方法 

 

 

Filters

翻譯爲過濾器,用來修改變量的顯示結果。

語法: {{ value|filter_name:參數 }}

':'左右沒有空格沒有空格沒有空格

有空格報錯:

 

default  

{{ value|default:"nothing"}}

若是value值沒傳的話就顯示nothing

沒傳值或者布爾值爲False的彷佛都是顯示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] 。

數字和字符串類型的數字使用add,怎麼拼獲得的都是數字運算的結果;數字和非數字字符串使用add方法彷佛沒有結果;非數字字符串和非數字字符串,數字字符串和非數字字符串都是字符串拼接

 

lower

小寫

{{ value|lower }}

 

upper

大寫

{{ 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

若是字符串字符多於指定的字符數量,那麼會被截斷。截斷的字符串將以可翻譯的省略號序列(「...」)結尾。 truncatewords

參數:截斷的字符數

{{ value|truncatechars:9}}

 

date

日期格式化

{{ value|date:"Y-m-d H:i:s"}}

可格式化輸出的字符:點擊查看。  沒有%  M->i  S->s

 或者修改配置

USE_L10N = False

DATETIME_FORMAT="Y-m-d H:i:s"
#還有DATA_FORMAT TIME_FORMAT

safe

Django的模板中會對HTML標籤和JS等語法標籤進行自動轉義,緣由顯而易見,這樣是爲了安全。可是有的時候咱們可能不但願這些HTML元素被轉義,好比咱們作一個內容管理系統,後臺添加的文章中是通過修飾的,這些修飾多是經過一個相似於FCKeditor編輯加註了HTML修飾符的文本,若是自動轉義的話顯示的就是保護HTML標籤的源文件。爲了在Django中關閉HTML的自動轉義有兩種方式,若是是一個單獨的變量咱們能夠經過過濾器「|safe」的方式告訴Django這段代碼是安全的沒必要轉義。 轉義是防止XSS攻擊的

好比:

value = "<a href='#'>點我</a>"

{{ value|safe}}

若是博客評論裏面能夠將js插入到程序裏面,而後這是一個循環一萬次的alert,那麼老是進不了網頁,而在頁面老是彈出alert框,直到循環結束。某些網站就是這樣,陷入死循環退不出去瀏覽器,只能重啓瀏覽器了

爲了安全起見,會變成字符串展現在頁面,若是想讓它變成程序使用,添加 safe

 

沒有safe的是被轉義過了的,因此在頁面不是a標籤顯示出來,而是純文本顯示。

若是傳進的有safe,那麼safe前面傳進的是不斷循環alert,那麼這個網頁就會執行不少這次alert而進不了網頁。它的做用就是告訴django這裏不須要轉義

自定義filter

自定義過濾器只是帶有一個或兩個參數的Python函數:

  • 變量(輸入)的值 - -不必定是一個字符串
  • 參數的值 - 這能夠有一個默認值,或徹底省略

例如,在過濾器{{var | foo:「bar」}}中,過濾器foo將傳遞變量var和參數「bar」

自定義filter代碼文件擺放位置:

複製代碼
app01/
    __init__.py
    models.py
    templatetags/  # 在app01下面新建一個package package
        __init__.py
        app01_filters.py  # 建一個存放自定義filter的py文件
    views.py
複製代碼

 

編寫自定義filter

複製代碼
from django import template
register = template.Library()


@register.filter
def fill(value, arg):
    return value.replace(" ", arg)


@register.filter(name="addSB")
def add_sb(value):
    return "{} SB".format(value)
複製代碼

使用自定義filter

複製代碼
{# 先導入咱們自定義filter那個文件 #}
{% load app01_filters %}

{# 使用咱們自定義的filter #}
{{ somevariable|fill:"__" }}
{{ d.name|addSB }}
複製代碼

沒有導入自定義過濾器:導入模塊,直接使用app下模塊中的函數

已導入,仍是報錯:'my_tags' is not a registered tag library. Must be one of:

遇到這個,第一步重啓項目。報錯變了

 

緣由,L應該大寫,Library()

 實現替換:

命名錯誤,在python這個包的init文件裏隨便寫點東西,報錯。

這裏名稱必須正確且與這個一致,寫錯會報錯:

手動建立的一個目錄而不是在pycharm中建立的包也行,可是沒有init文件,能夠補充一個,不過儘可能仍是建立包好些;

 

from django import template
registers=template.Library()

@registers.filter
def fill(value, arg):  #最多兩個參數,一個過濾器的變量,一個你想要的參數
    return value.replace(" ", arg) #將渲染值中的空格替換爲你想要的arg

@registers.filter(name="addSB")
def add_sb(value):   #給要渲染的值作一個操做,並給過濾器函數起個名字
    return "{} SB".format(value)
            #第二個傳參要不要都行。將傳進來作渲染的數據通過自定義過濾器作一次操做以後

 過濾器另取個名以後,函數名就無效了:

改爲新起的名字就行了:

 

Tags

for

根據多個值,對每一個值作不一樣的操做

<ul>
{% for user in user_list %}
    <li>{{ user.name }}</li>
{% endfor %}
</ul>

for循環可用的一些參數:

Variable Description
forloop.counter 當前循環的索引值(從1開始)
forloop.counter0 當前循環的索引值(從0開始)
forloop.revcounter 當前循環的倒序索引值(到1結束)
forloop.revcounter0 當前循環的倒序索引值(到0結束)
forloop.first 當前循環是否是第一次循環(布爾值)
forloop.last 當前循環是否是最後一次循環(布爾值)
forloop.parentloop 本層循環的外層循環

 

 當前循環的索引值(從0開始)

循環計數倒敘,但不影響列表取值順序:

倒敘循環計數,索引最值小爲0  當前循環的倒序索引值(到0結束)

 當前循環是否是第一次循環(布爾值) 當前循環是否是最後一次循環(布爾值)

若是隻有一個元素,那麼既是第一個也是最後一個 

 若是隻是打印forloop那麼顯示的是一個字典,字典裏有剛纔的那些變量,而後.出來值,還有一個就是parentloop循環是空值,由於這裏沒有使用外層循環

如今傳進去是一個列表裏面套着幾個列表:取出來每一個元素都是列表;

如今展現列表裏面的內容,須要再來一次內層循環:

每一行都是一個外層循環,一行中的每列都是在內層循環。一行中的每列的parentloop都是相同的,是同一個外層循環,prentloop的rarentloop沒有值,由於父的循環往上就沒有循環了

第二行就是循環計數第二個的外層循環,而後當前外層循環下進行內層循環展現每列的內容

last和first是隻的是每一個for循環的

將表格偶數列變成紅色字體:若是循環計數是偶數,那麼在內存循環中給這列加上顏色

 

若是想要實現偶數行而且是偶數列的單元格是紅色字:那麼加一個and共判斷兩個條件。外層定義行,內層定義了列。內層中獲取它的循環序數,也能獲取外層循環的序號;

偶數行和偶數列才變紅:內層循環判斷,知足循環序數是偶數且父循環序數也是偶數才添加樣式

 

for ... empty

複製代碼
<ul>
{% for user in user_list %}
    <li>{{ user.name }}</li>
{% empty %}
    <li>空空如也</li>
{% endfor %}
</ul>
複製代碼
    <table border="1">
        <thead>
            <tr>
                <th>序號</th>
                <th>ID</th>
                <th>書名</th>
                <th>出版社</th>
                <th>操做</th>
            </tr>
        </thead>
        <tbody>
            {% for book in books %}
                <tr>
                    <td>{{ forloop.counter }}</td>
                    <td>{{ book.pk }}</td>
                    <td>{{ book.title}}</td>
                    <td>{{ book.pub}}</td>
                    <td><a href="/del_book/?pk={{ book.pk }}">刪除</a>
                        <a href="/edit_book/?pk={{ book.pk }}">編輯</a>
                    </td>
                </tr>
            {% empty %}
                <td colspan="5" style="text-align: center;">沒有相關的數據</td>
            {% endfor %}
        </tbody>
View Code

將數據都刪除 

若是數據庫中沒有查詢到數據,這樣顯示不友好:

當顯示爲空的時候給用戶一個提示,而不是誤覺得有問題:

再讓它居中一下。合併一下。

 

if,elif和else

複製代碼
{% if user_list %}
  用戶人數:{{ user_list|length }}
{% elif black_list %}
  黑名單數:{{ black_list|length }}
{% else %}
  沒有用戶
{% endif %}
 
複製代碼

 

固然也能夠只有if和else

{% if user_list|length > 5 %}
  七座豪華SUV
{% else %}
    黃包車
{% endif %}

 

if語句支持 and 、or、==、>、<、!=、<=、>=、in、not in、is、is not判斷。

pycharm中連續比較 真:比較原理是  10>5是真,5>1是真,兩次比較結果再and作個比較,結果是真

控制檯中連續比較 假:比較原理是10>5是true, true>1比較是false。所以兩種比較方式不一樣,結果不一樣

 以下在js控制檯中就顯示true了,10>5是true ,true==1 結果就是true

模板語言和js是相同的,連續大於要空格,雖然報紅可是不影響結果顯示

不能使用1+2==判斷,而是要用過濾器計算而後判斷是否==

 

 

with

定義一箇中間變量。(定義變量,起別名)

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

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

hobby_list.0.2

內容太長或者是列表中連續索引取值而不能清楚取值是什麼,這時候用 with起個別名

csrf_token

這個標籤用於跨站請求僞造保護。

CSRF(Cross-site request forgery)跨站請求僞造,也被稱爲「One Click Attack」或者Session Riding,一般縮寫爲CSRF或者XSRF,是一種對網站的惡意利用。

瞭解鏈接:SQL注入、XSS以及CSRF分別是什麼?

在頁面的form表單裏面寫上{% csrf_token %}

跨站請求的理解:

用戶 a 服務器b 服務器c
從a到b請求,b返回a中可能有form表單。表單中action提交的地址常常不寫,不寫默認是提交到當前的地址。若是form表單中的地址是另外一個網站的地址(服務器c),這樣你的post請求就不是服務器b,而是去請求服務器c另外一個網站的了,這就叫跨站請求。對於服務器c來講它沒有作任何校驗,任何人都能對它進行post請求


對於我們來講應該是從a請求c,獲取到頁面,而後填寫帳號密碼以及轉帳的用戶和金額,填寫完後點擊提交post請求進行轉帳。若是你是不當心點擊廣告等進入的是釣魚網站服務器b等等,這樣你就說從b中獲取的轉帳提交網頁,釣魚網站的form表單中沒有填寫action,那麼post請求的是釣魚網站b,可是服務器B中的網站寫了c的ation。那麼你作的是c的post轉帳請求,看着是如出一轍的是提交到c的,可是若是b的請求網頁中內部作了一些修改將你的轉帳帳號修改爲了他人的帳號,那麼你就轉帳到了非法帳戶中了,這客戶就產生了損失。c不能隨便就能提交post請求的,須要校驗,不承認從別人的服務器form表單提交過來的請求。正常的應該是從a請求c獲取的form標籤再提交到c。那麼應該怎樣區別出是c本身的form提交仍是b跨站來的form表單提交給b呢?那麼服務器c就要作個標記,用戶獲取到它的網頁並用這個網頁提交post請求那麼會把標記提交回來。若是是從b獲取的form表單頁面那麼a是沒有c給的標記,這樣a寫好form表單以後再提交到c那麼就校驗不經過了。
假如a是從b拿到的請求,b返回a的頁面。這時a又從c出得到了請求c須要攜帶的標記,再去往c發送請求,這樣c也就承認它了。這就是跨站請求僞造,a從c經過csrf從c獲取到標記而後渲染到a從c獲取的form表單頁面,這樣c處校驗跨站請求就能經過,不然不能經過校驗就不能用b的form表單post提交到action是c地址的c服務器

 在配置中把這個註釋去掉:

這下post請求就會被拒絕了。由於當前服務器還不能肯定是誰的網頁發送的post請求

全部要想本身發出去的頁面中提交的post請求能經過校驗,那麼要在發送出去的網頁中添加標籤 {% csrf_token %},標籤寫在form表單外的時候以下。

 

這樣網頁並無顯示什麼不一樣。可是網頁中有了一個{% csrf_token %}渲染出來的類型是隱藏的input標籤,名字是csrf中間件token,值是一串字符

 這樣的話我要請求,就能夠拿到下面三個鍵值對,其中包括csrf的token。

標籤寫在form表單外面get能渲染token進模板,可是post沒有獲取到token

將它放在form表單中才能在post請求獲取到csrf中間件的token值,才能在服務器端根據這個值作校驗,校驗成功才能正常訪問,不然403拒絕

 

 

註釋

{# ... #}     #這個註釋不作渲染
<!-- {{可使用渲染的內容}} --> #這個註釋作渲染,可是不在瀏覽器上展現出來,在開發工具的元素中能夠看到它是存在的,它做爲代碼提示用的

 

注意事項

1. Django的模板語言不支持連續判斷,即不支持如下寫法:

{% if a > b > c %}
...
{% endif %}

2. Django的模板語言中屬性的優先級大於方法

def xx(request):
    d = {"a": 1, "b": 2, "c": 3, "items": "100"}
    return render(request, "xx.html", {"data": d})

如上,咱們在使用render方法渲染一個頁面的時候,傳的字典d有一個key是items而且還有默認的 d.items() 方法,此時在模板語言中:

{{ data.items }}

默認會取d的items key的值。

母板

複製代碼
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="x-ua-compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Title</title>
  {% block page-css %}
  
  {% endblock %}
</head>
<body>

<h1>這是母板的標題</h1>

{% block page-main %}

{% endblock %}
<h1>母板底部內容</h1>
{% block page-js %}

{% endblock %}
</body>
</html>
複製代碼

注意:咱們一般會在母板中定義頁面專用的CSS塊和JS塊,方便子頁面替換。

下面的書籍列表頁面:

和下面的頁面能夠作成一致的,也須要用下面的出版社樣式,若是隻是複製粘貼使用共有展現的東西的話,可能複製出問題,並且多個頁面中含有的重複的代碼特別多。而且一個頁面作了公共部分的修改了,那麼每一個頁面都要作修改,這是代碼重複的問題,那麼代碼重複須要一直複製粘貼不少次,python中減小代碼重複是寫函數和類。父類裏面寫個屬性,方法,用的時候子類繼承這個父類,每一個子類想用不一樣的方法和屬性那麼從新定義,覆蓋掉父類中相同的方法和屬性。這是繼承,繼承在模板頁面也是相似的

那麼1處,2處的公共的部分須要分出來做爲模板 ,而3處做爲變化的要替換的內容;

下面就建立基礎模板,並刪掉上面那個網頁中多餘出來的變化的部分:

先把咱們須要的模板訪問展現出來,1處就是變化的部分,其它部分是公共的功能,已經把公共的部分提出了了。

 

在你刪掉的那部分代碼處添加block塊:它就至關於公共的類和方法。

建立母版的思想就是將頁面公共的地方提取出來,將須要子頁面都須要添加內容的地方添加block塊,而後子頁面中用代碼將這個block塊替換掉

publisher_list.html這個頁面中將公共的部分刪掉,並將剛纔刪掉的部分留下,導入base.html母版,刪掉的部分做爲變化的替換掉上面名稱爲content的block塊。

<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>魔降風雲變</title>
    <link rel="stylesheet" href="/static/plugins/bootstrap-3.3.7-dist/css/bootstrap.css">
    <link href="/static/css/dashboard.css" rel="stylesheet">

</head>
{#<body>#}

<body>

<nav class="navbar navbar-inverse navbar-fixed-top">
    <div class="container-fluid">
        <div class="navbar-header">
            <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar"
                    aria-expanded="false" aria-controls="navbar">
                <span class="sr-only">Toggle navigation</span>
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
            </button>
            <a class="navbar-brand" href="#">圖書管理系統</a>
        </div>
        <div id="navbar" class="navbar-collapse collapse">
            <ul class="nav navbar-nav navbar-right">
                <li><a href="#">Dashboard</a></li>
                <li><a href="#">Settings</a></li>
                <li><a href="#">Profile</a></li>
                <li><a href="#">Help</a></li>
            </ul>
            <form class="navbar-form navbar-right">
                <input type="text" class="form-control" placeholder="Search...">
            </form>
        </div>
    </div>
</nav>

<div class="container-fluid">
    <div class="row">
        <div class="col-sm-3 col-md-2 sidebar">
            <ul class="nav nav-sidebar">
                <li class="active"><a href="/publisher_list/">出版社列表 <span class="sr-only">(current)</span></a></li>
                <li><a href="#">Reports</a></li>
            </ul>
        </div>
        <div class="col-sm-9 col-sm-offset-3 col-md-10 col-md-offset-2 main">
            <div class="panel panel-primary">
                <div class="panel-heading">
                    <h3 class="panel-title">出版社列表</h3>
                </div>
                <div class="panel-body">
                  <a class="btn btn-success btn-sm" href="/add_publisher">新增</a>
                    <div class="table-responsive">
                        <table class="table table-striped">
                            <thead>
                            <tr>
                                <th>序號</th>
                                <th>ID</th>
                                <th>名稱</th>
                                <th>操做</th>
                            </tr>
                            </thead>
                            <tbody>
                            {% for publisher in all_publishers %}
                                <tr>
                                    <td>{{ forloop.counter }}</td>
                                    <td>{{ publisher.pk }}</td>
                                    <td>{{ publisher.name }}</td>
                                    <td>
                                        <a class="btn btn-danger btn-sm" href="/del_publisher/?id={{ publisher.pk }}">刪除</a>
                                        <a class="btn btn-success btn-sm" href="/edit_publisher/?id={{ publisher.pk }}">編輯</a>
                                    </td>
                                </tr>
                            {% endfor %}

                            </tbody>
                        </table>
                    </div>
                </div>
            </div>

        </div>
    </div>
</div>


</body>

</html>
操做前publiser_list.html

 

/publisher_list/ 導入模板成功顯示公共功能部分

在publisher.html頁面中再添加模板中能夠替換的block塊content部分。在子html中將剛纔刪除的內容添加進去:

而後子頁面就使用繼承的方法正常顯示了

下面把下面的book_list.html頁面也修改爲這個模板的。

這裏只顯示模板沒有顯示book的數據,由於以前這裏函數改爲了模板頁面了,改回來

book頁面也用這個模板渲染出來了:

將表格樣式用publisher_list.html中的樣式修改一下:

左邊書籍列表添加要在base母版修改添加:

雖然實現了,可是都是被選中狀態,由於這兩個標籤都有active類

若是沒有這個類是未被選中狀態:

那麼就用block塊的方法代替它 ,點擊哪一個頁面的時候先將模板全部的變成空,而後將點擊的要顯示這個html添加active類 

重名了:

換個名字,如今都是未被選中:

給這裏默認填充一個內容讓它被選中:

而後在子中替換掉:實現點擊誰只有誰被選中並展現出來

我也能夠直接用publisher.html作母版,將變化的內容寫在block裏面,而後子繼承父,子中將對應block內容重寫替換掉父的。拿一個子類當成父類,其它繼承這個父類。咱們要作的就是把頁面中特殊的替換掉。用base或者某個頁面作母版看狀況而定

 

總結:

母版

就是一個普通HTML提取多個頁面的公共部分 定義block塊

繼承:

  1. {% extends ‘base.html’ %}

  2. 重寫block塊 —— 寫子頁面獨特的內容

注意的點:

  1. {% extends 'base.html' %} 寫在第一行 前面不要有內容 有內容會顯示

  2. {% extends 'base.html' %} 'base.html' 加上引號 否則當作變量去查找

  3. 把要顯示的內容寫在block塊中

  4. 定義多個block塊,定義 css js 塊

寫在第一行母版以前:一、{% extends 'base.html' %} 寫在第一行 前面不要有內容 有內容會顯示

寫在塊的外面;{% extends 'base.html' %} 'base.html' 加上引號 否則當作變量去查找

把繼承中的模板去掉引號:它會把它當作變量(或者變量沒有正確獲取)並報錯:Invalid template name in 'extends' tag: ''. Got this from the 'base.html' variable.

那麼將母版以變量的形式從函數中傳進來並在子中繼承:之後想要靈活點,能夠換模板那麼就將母版以變量的形式傳遞進來。

注意:咱們有的時候想要子頁面有不一樣的樣式或js,而不是隻能使用父的,所以咱們一般會在母板中定義頁面專用的CSS塊和JS塊,方便子頁面替換。

 

  {% block page-css %}
  
  {% endblock %}

<h1>母板底部內容</h1>
{% block page-js %}

{% endblock %}

 

 

繼承母板

在子頁面中在頁面最上方使用下面的語法來繼承母板。

{% extends 'layouts.html' %}

塊(block)

經過在母板中使用{% block  xxx %}來定義"塊"。

在子頁面中經過定義母板中的block名來對應替換母板中相應的內容。

{% block page-main %}
  <p>世情薄</p>
  <p>人情惡</p>
  <p>雨送黃昏花易落</p>
{% endblock %}

組件

能夠將經常使用的頁面內容如導航條,頁尾信息等組件保存在單獨的文件中,而後在須要使用的地方按以下語法導入便可。

組件就是實現一角的功能的一小段代碼塊

{% include 'navbar.html' %}
新增出版社頁面:
我想在添加出版社列表中也有這個導航欄

那麼這裏也可使用模板和繼承,那麼我把base的左邊框和內容部分替換掉,這樣的話要替換的比較多。 更方便的是把導航欄作成一個組件,將它導入到新增頁面,就像Python裏的模塊,想用導入就好了。

如今把母版裏的導航欄剪切下來:

剪切下來繼承使用它的就沒有這個導航欄了,剪切下來放到一個html文件

可是頁面仍是要使用導航欄的功能,導入這個組件便可,這就是一部分代碼塊(放到裏面就能使用展現想要效果的代碼塊;將一個功能剪切出去放到html文件就實現了一個組件,這個代碼塊就是組件)

而後直接導入組件  include 加組件文件名字

{% include 'nav.html' %}

以下就將以前想要添加的部分功能添加到這個頁面了:由於多個頁面都是導入的這一個組件,那麼只要修改這個組件,好比把圖書管理系統名字改掉,只須要在組件 中修改就能夠把全部用這個組件的頁面顯示都修改爲新的名字了。

一小段代碼塊

 

靜態文件相關

若是未來部署的過程中,靜態文件別名想要作個變動,不想用這個名字了,那麼換了名字以後就這樣了:

1處修改,2和3的引用使用的固定的沒有修改這樣4處樣式就沒有使用上了

而且這裏報錯找不到,由於別名修改了而引用路徑沒有修改。引用必須和別名一致才能找到樣式。那麼若是手動修改引用的別名的話,修改那麼多個確定不方便

那麼把這個別名的引用變成變量的那種形式來使用,讓它本身去找這個別名而後替換成當前配置的別名;

首先導入,而後使用,若是沒有傳參會報錯至少一個傳參,開頭有沒有/均可以:

它會給你作上拼接:

staticfiles也能夠的

導入static使用這個tag那麼獲取到的是靜態目錄的那個別名:

使用它來的話這裏不能加/,就是獲取別名而後渲染上了,不會給你添加/

 

{% load static %}
<img src="{% static "images/hi.jpg" %}" alt="Hi!" />

引用JS文件時使用:

{% load static %}
<script src="{% static "mytest.js" %}"></script>

某個文件多處被用到能夠存爲一個變量

{% load static %}
{% static "images/hi.jpg" as myphoto %}
<img src="{{ myphoto }}"></img>

使用get_static_prefix

{% load static %}
<img src="{% get_static_prefix %}images/hi.jpg" alt="Hi!" />

或者

{% load static %}
{% get_static_prefix as STATIC_PREFIX %}

<img src="{{ STATIC_PREFIX }}images/hi.jpg" alt="Hi!" />
<img src="{{ STATIC_PREFIX }}images/hi2.jpg" alt="Hello!" />

自定義simpletag

和自定義filter相似,只不過接收更靈活的參數。

定義註冊simple tag  。simpletag前面和filter類似,就是使用不一樣的裝飾器傳遞的參數數量不一樣

@register.simple_tag(name="plus")
def plus(a, b, c):
    return "{} + {} + {}".format(a, b, c)

使用自定義simple tag

{% load app01_demo %}

{# simple tag #}
{% plus "1" "2" "abc" %}

彷佛這個裝飾後面加不加括號都行

 

inclusion_tag

多用於返回html代碼片斷

組件也是一個代碼段,與組件的區別是組件是固定的,而這個是靈活的能夠傳變量進去先進行渲染,而後再在使用這個標籤的地方替換成這個被變量渲染過的代碼段(導入)

示例:

templatetags/my_inclusion.py

複製代碼
from django import template

register = template.Library()


@register.inclusion_tag('result.html')
def show_results(n):
    n = 1 if n < 1 else int(n)
    data = ["第{}項".format(i) for i in range(1, n+1)]
    return {"data": data}
複製代碼

templates/result.html

<ul>
  {% for choice in data %}
    <li>{{ choice }}</li>
  {% endfor %}
</ul>

templates/index.html

複製代碼
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="x-ua-compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>inclusion_tag test</title>
</head>
<body>

{% load my_inclusion %}

{% show_results 10 %}
</body>
</html>
 
複製代碼

 

使用下面的分頁:

可是這個是固定死的頁數,修改一下:

1)1處寫函數,將參數傳到函數中。返回一個字典。這裏字典的一個值是1-10的列表吧,

2)1處將page函數返回值渲染page.html代碼段中的內容造成一個代碼段

3)3處導入這個模塊,使用這個標籤函數,並指定傳參。這樣引用並生成靈活可變更的page.html代碼段,並在這個頁面中渲染出來。

4)就至關於我生成一個可傳參修改變更的組件,而後將組件導入到須要的頁面。根據 須要產生細微差異

 

 

 

參考連接:https://www.cnblogs.com/maple-shaw/articles/9333821.html

相關文章
相關標籤/搜索