Django模板系統


 

 

 

 

 

官方文檔


常用語法

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

{{  }}和 {% %}

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

變量

{{ 變量名 }}

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

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

幾個例子:

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}) #傳字符串,數字,列表,字典等
復制代碼

模板中支持的寫法:

復制代碼
<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 塊

寫在第一行母版之前:1、{% 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

 


免責聲明!

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



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