Django基礎4.0,模板系統

Django4.0

-----借鑑:cls超:點擊這裏css

語法

語法 {{ 變量 }} {% 邏輯 %}

變量的使用和說明

在Django的模板語言中按此語法使用:{{ 變量名 }}。
  當模版引擎遇到一個變量,它將計算這個變量,而後用結果替換掉它自己。 變量的命名包括任何字母數字以及下劃線 ("_")的組合。 變量名稱中不能有空格或標點符號。
  深度查詢據點符(.)在模板語言中有特殊的含義。當模版系統遇到點("."),它將以這樣的順序查詢:
    字典查詢(Dictionary lookup)
    屬性或方法查詢(Attribute or method lookup)
    數字索引查詢(Numeric index lookup)html


  注意事項:前端

    •   若是計算結果的值是可調用的,它將被無參數的調用。 調用的結果將成爲模版的值。
    •   若是使用的變量不存在, 模版系統將插入 string_if_invalid 選項的值, 它被默認設置爲'' (空字符串)

舉個栗子:django

view中的代碼bootstrap

def index(request): import datetime s = "hello" l = [111, 222, 333] # 列表 dic = {"name": "yuan", "age": 18} # 字典 date = datetime.date(1993, 5, 2) # 日期對象 class Person(object): def __init__(self, name): self.name = name def dream(self): return 'dreamer' person_yuan = Person("chao") # 自定義類對象 person_egon = Person("yantao") person_alex = Person("jinxin") person_list = [person_yuan, person_egon, person_alex] return render(request, "index.html", {"l": l, "dic": dic, "date": date, "person_list": person_list}) # return render(request,"index.html",locals()) # 不建議,取出函數全部變量 #locals()獲取函數內容全部的變量,而後經過render方法給了index.html文件進行模板渲染,若是你圖省事,你能夠用它,可是不少多餘的變量也被傳進去了,效率低

 

 HTML模板中的寫法後端

<h4>{{s}}</h4> <h4>列表:{{ l.0 }}</h4> <h4>列表:{{ l.2 }}</h4> <h4>字典:{{ dic.name }}</h4> <h4>日期:{{ date.year }}</h4> <!--取列表的第1個對象的name屬性的值--> <h4>類對象列表:{{ person_list.0.name }}</h4> <!--取列表的第1個對象的dream方法的返回值,若是沒有返回值,拿到的是none--> <h4>類對象列表:{{ person_list.0.dream }}</h4> 注意: 調用對象裏面的方法的時候,不須要寫括號來執行,而且只能執行不須要傳參數的方法,若是你的這個方法須要傳參數,那麼模板語言不支持,不能幫你渲染

 

 過濾器的使用和說明

在Django的模板語言中,經過使用 過濾器 來改變變量的顯示。
  過濾器的語法: {{ value|filter_name:參數 }}
  使用管道符"|"來應用過濾器。
  例如:{{ name|lower }}會將name變量應用lower過濾器以後再顯示它的值。lower在這裏的做用是將文本全都變成小寫。
  注意事項:瀏覽器

    1. 過濾器支持「鏈式」操做。即一個過濾器的輸出做爲另外一個過濾器的輸入。
    2. 過濾器能夠接受參數,例如:{{ sss|truncatewords:30 }},這將顯示sss的前30個詞。
    3. 過濾器參數包含空格的話,必須用引號包裹起來。好比使用逗號和空格去鏈接一個列表中的元素,如:{{ list|join:', ' }}
    4. '|'左右沒有空格沒有空格沒有空格

   Django的模板提供了大約六十個內置過濾器安全

 

  default  若是一個變量是false或者爲空,使用給定的默認值。 不然,使用變量的值。app

{{ value|default:"nothing"}}  <!--若是value沒有傳值或者傳值爲空的話就顯示nothing-->

   lenght  返回值得長度,用做於字符串和列表編輯器

{{ value|length }} <!--返回value的長度,如 value=['a','b','c']的話 就顯示4-->

  filesizeformat  將值格式化爲一個 「人類可讀的」 文件尺寸 (例如 '13 KB''4.1 MB''102 bytes', 等等)

{{ value|filesizeformat }} <!--若是 value 是 123456789,輸出將會是 117.7 MB。-->

  slice  切片,若是 value="hello world",還有其餘可切片的數據類型

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

  date  時間格式化顯示,若是 value=datetime.datetime.now()

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

  safe  將字符串識別爲標籤,好比 value = "<a href='#'>點我</a>"   和   value="<script>alert('123')</script>"

{{ value|safe}}

  truncatechars  字符截斷

{{ value|truncatechars:9}} <!--注意:最後那三個省略號也是9個字符裏面的,也就是這個9截斷出來的是6個字符+3個省略號-->

  truncatewords  單詞截斷 在必定數量的字後截斷字符串,是截多少個單詞。例如 ‘hello girl hi baby yue ma’

{{ value|truncatewords:3}} <!--上面例子獲得的結果是 'hello girl h1...'-->

  cut  移除value中全部的與給出的變量相同的字符串

{{ value|cut:' ' }} <!--若是value爲'i love you',那麼將輸出'iloveyou'-->

  join  使用字符串鏈接列表,{{ list|join:', ' }},就像Python的str.join(list)

{{ value_list|join:'+' }}

 

標籤tags的使用和說明

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

for循環標籤

  沒有break之類的,複雜一些的功能,須要的話要用js實現

 循環一個字典 {% for key,value in d1.items %} {{ forloop.counter }} <li>{{ key }} -- {{ value }}</li> <!-凡是變量都要用兩個大標籤括起來--> {% endfor %}

 

for循環的其餘方法

forloop.counter 當前循環的索引值(從1開始),forloop是循環器,經過點來使用功能 forloop.counter0 當前循環的索引值(從0開始) forloop.revcounter 當前循環的倒序索引值(從1開始) forloop.revcounter0 當前循環的倒序索引值(從0開始) forloop.first 當前循環是否是第一次循環(布爾值) forloop.last 當前循環是否是最後一次循環(布爾值) forloop.parentloop 本層循環的外層循環的對象,再經過上面的幾個屬性來顯示外層循環的計數等 forloop.parentloop.counter

 

 

 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 %} <!--也是在if標籤結構裏面的-->
    <p>湊活吧</p> {% endif %}

 

  固然也能夠只有if和else

{% if user_list|length > 5 %}  <!--結合過濾器來使用--> 七座豪華SUV {% else %} 黃包車 {% endif %}

  if語句支持 and 、or、==、>、<、!=、<=、>=、in、not in、is、is not判斷,注意條件兩邊都有空格。

with語句

  給一個複雜的變量起別名

{% with total=business.employees.count %} {{ total }} <!--只能在with語句體內用--> {% endwith %}
或者 {% with business.employees.count as total %} {{ total }} {% endwith %}

 

csrf_token認證

  以post方式提交表單的時候,會報錯,以前settings裏面的中間件配置裏面把一個csrf的防護機制註銷了,自己不該該註銷的,而是經過驗證

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

  在頁面的form表單裏面(注意是在form表單裏面)任何位置寫上{% csrf_token %},這個東西模板渲染的時候替換成了<input type="hidden" name="csrfmiddlewaretoken" value="8J4z1wiUEXt0gJSN59dLMnktrXFW0hv7m4d40Mtl37D7vJZfrxLir9L3jSTDjtG8">,隱藏的,這個標籤的值是個隨機字符串,提交的時候,這個東西也被提交了,首先這個東西是咱們後端渲染的時候給頁面加上的,那麼當你經過我給你的form表單提交數據的時候,你帶着這個內容我就認識你,不帶着,我就禁止你,由於後臺咱們django也存着這個東西,和你這個值相同的一個值,能夠作對應驗證是否是我給你的token,存儲這個值的東西咱們後面再學,你先知道一下就好了,就像一個咱們後臺給這個用戶的一個通行證,若是你用戶沒有按照我給你的這個正常的頁面來post提交表單數據,或者說你沒有先去請求我這個登錄頁面,而是直接模擬請求來提交數據,那麼我就能知道,你這個請求是非法的,反爬蟲或者惡意攻擊個人網站,之後將中間件的時候咱們在細說這個東西,可是如今你要明白怎麼回事,明白爲何django會加這一套防護。

 

   示例:

<form action="/login/" method="post"> {% csrf_token %} 帳戶<input type="text" name="username"> 密碼<input type="text" name="password">
    <input type="submit">
</form>

 

 添加認證以前

添加認證以後

 

模板繼承

  Django模版引擎中最強大也是最複雜的部分就是模版繼承了。模版繼承可讓您建立一個基本的「骨架」模版,它包含您站點中的所有元素,而且能夠定義可以被子模版覆蓋的 blocks 。
  經過從下面這個例子開始,能夠容易的理解模版繼承:

 

base.html

<!DOCTYPE html>
<html lang="en">
<head>
    <link rel="stylesheet" href="style.css" />
    <title>{% block title %}My amazing site{% endblock %}</title>
</head>

<body>
    <div id="sidebar"> {% block sidebar %} <ul>
            <li><a href="/">Home</a></li>
            <li><a href="/blog/">Blog</a></li>
        </ul> {% endblock %} </div>

    <div id="content"> {% block content %}{% endblock %} </div>
</body>
</html>

  這個模版,咱們把它叫做 base.html, 它定義了一個能夠用於兩列排版頁面的簡單HTML骨架。「子模版」的工做是用它們的內容填充空的blocks。
  在這個例子中, block 標籤訂義了三個能夠被子模版內容填充的block。 block 告訴模版引擎: 子模版可能會覆蓋掉模版中的這些位置。
  子模版可能看起來是這樣的:

base2.html

{% extends "base.html" %} {% block title %}My amazing blog{% endblock %} {% block content %} {% for entry in blog_entries %} <h2>{{ entry.title }}</h2>
    <p>{{ entry.body }}</p> {% endfor %} {% endblock %}

  extends 標籤是這裏的關鍵。它告訴模版引擎,這個模版「繼承」了另外一個模版。當模版系統處理這個模版時,首先,它將定位父模版——在此例中,就是「base.html」。
  那時,模版引擎將注意到 base.html 中的三個 block 標籤,並用子模版中的內容來替換這些block。根據 blog_entries 的值,輸出可能看起來是這樣的:

 base2.html

<!DOCTYPE html>
<html lang="en">
<head>
    <link rel="stylesheet" href="style.css" />
    <title>My amazing blog</title>
</head>
 
<body>
    <div id="sidebar">
        <ul>
            <li><a href="/">Home</a></li>
            <li><a href="/blog/">Blog</a></li>
        </ul>
    </div>
 
    <div id="content">
        <h2>Entry one</h2>
        <p>This is my first entry.</p>
 
        <h2>Entry two</h2>
        <p>This is my second entry.</p>
    </div>
</body>
</html>

 

請注意,子模版並無定義 sidebar block,因此係統使用了父模版中的值。父模版的 {% block %} 標籤中的內容老是被用做備選內容(fallback)。
這種方式使代碼獲得最大程度的複用,而且使得添加內容到共享的內容區域更加簡單,例如,部分範圍內的導航。
  這裏是使用繼承的一些提示:

  • 若是你在模版中使用 {% extends %} 標籤,它必須是模版中的第一個標籤。其餘的任何狀況下,模版繼承都將沒法工做,模板渲染的時候django都不知道你在幹啥。
  • 在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.  將子頁面的內容和繼承的母版中block裏面的內容同時保留

 

也能夠給 {% endblock %} 標籤一個 名字 。例如:

{% block content %} pass {% endblock content %}

 

在大型模版中,這個方法幫你清楚的看到哪個  {% block %} 標籤被關閉了

不能再同一個模板中定義相同的名字

 

組件的使用和說明

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

{% include 'test.html' %}

 

  例如:有個以下的導航欄

test.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style> .c1{ background-color: red; height: 40px;
        }
    </style>
</head>
<body>

<div class="c1">
    <div>
        <a href="">xx</a>
        <a href="">dd</a>
    </div>
</div>

</body>
</html>

 

  嵌入導航欄的頁面

test_one.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body> {% include 'nav.html' %} <h1>組件示例</h1>
</body>
</html>

 

# 組件和插件的簡單區別
組件是提供某一完整功能的模塊,如:編輯器組件,QQ空間提供的關注組件 等。 而插件更傾向封閉某一功能方法的函數。 這二者的區別在 Javascript 裏區別很小,組件這個名詞用得很少,通常統稱插件。

 

自定義標籤和過濾器

自定義過濾器與標籤

  1. 在settings中的INSTALLED_APPS配置當前app,否則django沒法找到自定義的simple_tag.
  2. app應用文件夾中建立一個templatetags文件件,必須是這個名字
  3. templatetags文件夾中建立一個 xx.py文件,文件名字隨便起

 例如:

menu_setting.py

from django import template register = template.Library() # 不帶參數的過濾器
@register.filter def MyLebel1(sum): date = sum + "這是一條小尾巴~"
    return date # 帶參數的過濾器 最多兩個參數
@register.filter def MyLebel2(sum1,sum2): date = sum1 + sum2 return date # 自定義標籤
@register.simple_tag def mytag1(s1): s = s1+":小尾巴~"
    return s # 自定義標籤 多個參數
@register.simple_tag def mytag2(s1,s2,s3): s = s1+''+s2+''+s3+'是一隻貓'
    return s 

 

  在使用自定義simple_tag和filter的html文件中導入以前建立的 menu_setting.py

{% load menu_setting %}

 

   使用simple_tag和filter

<body>
<h1>你好 這是一個測試</h1> {% load menu_setting %}    # 導入templatetags/menu_setting {{ name|MyLebel1 }} {{ name|MyLebel2:"--這是一條小尾巴~" }} <h1> {% mytag1 name %} </h1>
<h1> {% mytag2 name "小黑" "小白"%} </h1> {% func1 %} {% func2 name_list %} <p>結束</p>
</body>

 

  注意:filter能夠用在if、for等語句後,simple_tag不能夠

{% if num|MyLebel1:30 > 100 %} {{ num|MyLebel1:30 }} {% endif %}

 

inclusion_tag

 多用於返回html代碼片斷

  示例:

templatetags/menu_setting.py

 
 
from django import template register = template.Library()

# 不帶參數的
@register.inclusion_tag("inclusion.html") def func1(): return {"date":[11,22,33]}
# 帶參數的 @register.inclusion_tag(
"inclusion.html") def func2(s1): return {"date":s1}

  func的return數據,傳給了inclusion.html,做爲模板渲染的數據,將inclusion.html渲染好以後,做爲一個組件,生成到調用這個func的地方

templates/snippets/inclusion.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>inclusion</title>
</head>
<body>
<ul> {% for a in date %} <li>{{ a }}</li> {% endfor %} </ul>
</body>
</html>

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 menu_setting %}  # 導入templatetags/menu_setting
{% func1 %}   無參數的 {% func2 1i %} 有參數的 </body> </html>

 

靜態文件相關

js、css、img等都叫作靜態文件,那麼關於django中靜態文件的配置,咱們就須要在settings配置文件裏面寫上這寫內容:

# STATIC_URL = '/xxx/' #別名,隨便寫名字,可是若是你更名字,別忘了前面頁面裏面若是你是經過/xxx/bootstrap.css的時候,若是這裏的別名你改爲了/static/的話,你前端頁面的路徑要改爲/static/bootstrap.css。因此咱們都是用下面的load static的方式來使用靜態文件路徑
STATIC_URL = '/static/' #別名
 STATICFILES_DIRS = [ os.path.join(BASE_DIR,'jingtaiwenjian'), #注意別忘了寫逗號,第二個參數就是項目中你存放靜態文件的文件夾名稱
]

 

  目錄:別名也是一種安全機制,瀏覽器上經過調試臺你可以看到的是別名的名字,這樣別人就不能知道你靜態文件夾的名字了,否則別人就能經過這個文件夾路徑進行攻擊。

 

前端頁面引入靜態文件的寫法,由於別名也可能會修改,因此使用路徑的時候經過load static來找到別名,經過別名映射路徑的方式來獲取靜態文件

 方法一:

<head>
    <meta charset="UTF-8">
    <title>首頁</title>
    <link rel="stylesheet" href="/static/css1.css">
</head>

 

 {% static %}

{% load static %} # 導入css <link rel="stylesheet" href={% static "css1.css" %}> # 導入圖片之類 <img src="{% static "images.jpg" %}" alt="Hi!" />

   引入js文件時要是用:

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

   某個文件多處備用能夠存爲一個變量(起別名)

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

 

 {% get_static_prefix %}

{% load static %} # css <link rel="stylesheet" href={% get_static_prefix %}css1.css> # 圖片 <img src="{% get_static_prefix %}images.jpg" alt="Hi!" />

   或者 起別名

{% load static %} {% get_static_prefix as STATIC_PREFIX %} # css <link rel="stylesheet" href={{ STATIC_PREFIX}}css1.css> # 圖片 <img src="{{ STATIC_PREFIX }}images/hi.jpg" alt="Hi!" />
<img src="{{ STATIC_PREFIX }}images/hi2.jpg" alt="Hello!" />
相關文章
相關標籤/搜索