Django 模板層

模板

1、模板語法之變量

  • {{ comment.create_time|date:"Y-m-d H:i:s" }}
  • {{ bio|truncatewords:"30" }}
  • {{ my_list|first|upper }}
  • {{ name|lower }}
  • {{ forloop.counter }}
  • {{ forloop.first }}
  • {{ forloop.last }}

在 Django 模板中遍歷複雜數據結構的關鍵是句點字符, 語法: {{var_name}}css

?
1
2
3
4
5
6
<h4>{{s}}< / h4>
<h4>列表:{{ l. 0 }}< / h4>
<h4>列表:{{ l. 2 }}< / h4>
<h4>字典:{{ dic.name }}< / h4>
<h4>日期:{{ date.year }}< / h4>
<h4>類對象列表:{{ person_list. 0.name }}< / h4>

2、模板之過濾器

語法:{{obj|filter__name:param}}html

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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 = "hello world"
{{ value| slice : "2:-1" }}
  
truncatechars:
若是字符串字符多於指定的字符數量,那麼會被截斷。截斷的字符串將以可翻譯的省略號序列(「...」)結尾。
參數:要截斷的字符數
{{ value|truncatechars: 9 }}
  
safe:Django的模板中會對HTML標籤和JS等語法標籤進行自動轉義,這樣是爲了安全。若是不但願HTML元素被轉義,能夠這樣:
value = "<a href=" ">點擊</a>"
{{ value|safe}}

這裏簡單介紹一些經常使用的模板的過濾器,更多詳見python

3、模板之標籤

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

一、for標籤

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
"""
遍歷每個元素:
{% for person in person_list %}
     <p>{{ person.name }}</p>
{% endfor %}
能夠利用{% for obj in list reversed %}反向完成循環。
 
遍歷一個字典:
{% for key,val in dic.items %}
     <p>{{ forloop.counter }} {{ key }}:{{ val }}</p>
{% endfor %}
注:循環序號能夠經過{{ forloop }}顯示  
 
forloop.counter            The current iteration of the loop (1-indexed)
forloop.counter0           The current iteration of the loop (0-indexed)
forloop.revcounter         The number of iterations from the end of the loop (1-indexed)
forloop.revcounter0        The number of iterations from the end of the loop (0-indexed)
forloop.first              True if this is the first time through the loop
forloop.last               True if this is the last time through the loop
"""

二、for ... empty

?
1
2
3
4
5
6
<! - - for 標籤帶有一個可選的{ % empty % } 從句,以便在給出的組是空的或者沒有被找到時,能夠有所操做。 - - >
{ % for person in person_list % }
     <p>{{ forloop.counter0 }} {{ person.name }} , {{ person.age }}< / p>
{ % empty % }
     <p>列表爲空< / p>
{ % endfor % }

三、if 標籤

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<! - - 注意: filter 能夠用在 if 等語句後,simple_tag不能夠 - - >
{ % if i|multi_fliter: 10 > 100 % }
     <p> 100 < / p>
{ % else % }
     <p>{{ i }}< / p>
{ % endif % }
 
<! - - 多分支 - - >
{ % if num > 100 or num < 0 % }
     <p>無效< / p>
{ % elif num > 80 and num < 100 % }
     <p>優秀< / p>
{ % else % }
     <p>湊活吧< / p>
{ % endif % }

四、with

?
1
2
3
4
5
<! - - 使用一個簡單地名字緩存一個複雜的變量 - - >
{ % with person_list. 1.name as n % }
     {{ n }}
     {{ n }}
{ % endwith % }

五、csrf_token

?
1
2
3
4
5
<form action = " " method=" post">
     { % csrf_token % }  <! - - 這個標籤用於跨站請求僞造保護 - - >
     < input type = "text" name = "user" >
     < input type = "submit" >
< / form>

4、自定義標籤和過濾器

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
"""
一、在settings中的INSTALLED_APPS配置當前app,否則django沒法找到自定義的simple_tag.
二、在app中建立templatetags包(包名只能是templatetags)
三、建立任意 .py 文件,如:my_tags.py
四、在使用自定義simple_tag和filter的html文件中導入以前建立的 my_tags.py
五、使用simple_tag和filter(如何調用)
注意:filter能夠用在if等語句後,simple_tag不能夠
"""
 
#settings.py
INSTALLED_APPS = [
     'django.contrib.admin' ,
     'django.contrib.auth' ,
     'django.contrib.contenttypes' ,
     'django.contrib.sessions' ,
     'django.contrib.messages' ,
     'django.contrib.staticfiles' ,
     "app01" , #配置當前app
]
 
# app01.templatetags.my_tags.py
from django import template
from django.utils.safestring import mark_safe
 
register = template.Library()  # register的名字是固定的,不可改變
 
@register . filter       #自定義過濾器最多2個參數
def multi_fliter(v1, v2):
     return v1 * v2
 
@register .simple_tag   #自定義標籤,沒有參數個數限制
def multi_tag(v1, v2, v3):
     return v1 * v2 * v3
 
@register .simple_tag
def my_input( id , arg):
     result = "<input type='text' id='%s' class='%s' />" % ( id , arg,)
     return mark_safe(result)
 
#模板中:
"""
{% load my_tags %}  <!--注意:這塊更改過要重啓項目-->
# num = 8
<p>{{ num|multi_fliter:20 }}</p>
<p>{% multi_tag 7 9 6 %}</p>
 
<!--注意:filter能夠用在if等語句後,simple_tag不能夠-->
{% if num|multi_fliter:10 > 100 %}
     <p>100</p>
{% else %}
     <p>{{ num }}</p>
{% endif %}
"""

5、模板之inclusion_tag

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
# app01.templatetags.my_tags.py
 
from django import template
from django.db.models import Count
from app01 import models
register = template.Library()
 
 
@register .simple_tag
def multi_tag(x,y):
     return x * y
 
 
@register .inclusion_tag( "classification.html" )
def get_classification_style(username):
 
     user = models.UserInfo.objects. filter (username = username).first()
     blog = user.blog
 
     cate_list = models.Category.objects. filter (blog = blog).values( "pk" ).annotate(c = Count( "article__title" )).values_list( "title" , "c" )
 
     tag_list = models.Tag.objects. filter (blog = blog).values( "pk" ).annotate(c = Count( "article" )).values_list( "title" , "c" )
 
     date_list = models.Article.objects. filter (user = user).extra(select = { "y_m_date" : "date_format(create_time,'%%Y/%%m')" }).values( "y_m_date" ).annotate(c = Count( "nid" )).values_list( "y_m_date" , "c" )
 
 
     return { "blog" :blog, "cate_list" :cate_list, "date_list" :date_list, "tag_list" :tag_list}
 
 
#模板中:使用
"""
  <div class="col-md-3 menu">
              {% load my_tags %}
              {% get_classification_style username %}
  </div>
"""
 
 
#templates.classification.html
"""
  <div>
     <div class="panel panel-warning">
                 <div class="panel-heading">個人標籤</div>
                 <div class="panel-body">
                     {% for tag in tag_list %}
                         <p><a href="/{{ username }}/tag/{{ tag.0 }}">{{ tag.0 }}({{ tag.1 }})</a></p>
                     {% endfor %}
 
                 </div>
             </div>
 
     <div class="panel panel-danger">
         <div class="panel-heading">隨筆分類</div>
         <div class="panel-body">
             {% for cate in cate_list %}
                 <p><a href="/{{ username }}/category/{{ cate.0 }}">{{ cate.0 }}({{ cate.1 }})</a></p>
             {% endfor %}
         </div>
     </div>
 
     <div class="panel panel-success">
         <div class="panel-heading">隨筆歸檔</div>
         <div class="panel-body">
             {% for date in date_list %}
                 <p><a href="/{{ username }}/archive/{{ date.0 }}">{{ date.0 }}({{ date.1 }})</a></p>
             {% endfor %}
         </div>
     </div>
  </div>
"""

6、模板繼承 (extend)

  • 不能在一個模版中定義多個相同名字的 block 標籤。
  • 爲了更好的可讀性,你也能夠給你的 {% endblock %} 標籤一個 名字 。例如:{% block content %}...{% endblock content %}
  • 子模版沒必要定義所有父模版中的blocks
  • {% extends 'base.html' %}

一、製做模板

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<! - - 模版 base.html - - >
<!DOCTYPE html>
<html lang = "en" >
<head>
     <meta charset = "UTF-8" >
     { % block title % }
     <title>base< / title>
     { % endblock % }
 
     { % block css % } { % endblock % }
< / head>
<body>
 
<div class = "header" >< / div>
<div class = "container" >
     <div class = "row" >
         <div class = "col-md-3" >
             { % include 'left1.html' % }  <! - - 引入小組件 - - >
             { % include 'ad.html' % }  <! - - 引入小組件 - - >
         < / div>
         <div class = "col-md-9" >
              
             { % block con % }
               <h4>content< / h4>
             { % endblock content % }  <! - - 更好的可讀性 - - >
             
         < / div>
     < / div>
< / div>
 
{ % block js % }{ % endblock % }
< / body>
< / html>

二、繼承模板

?
1
2
3
4
5
6
7
8
9
10
11
12
{ % extends 'base.html' % } <! - - 它必須是模版中的第一個標籤。 - - >
 
{ % block title % }
<title>orders< / title>
{ % endblock % }
 
{ % block con % }
{{ block. super }}  <! - - 獲取模板中con的內容 - - >
<h4>訂單< / h4>
{ % endblock con % }
 
<! - - order.html - - >

7、模板多對多調用

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
class Student(models.Model):
     name = models.CharField(max_length = 128 )
  
class Course(models.Model):
     name = models.CharField(max_length = 128 )
     students = models.ManyToManyField( 'Student' )
  
正向查詢:
從course往student查
def test(request):
     course = models.Course.objects.get(pk = 1 )
     return render(request, 'course.html' , locals ())
  
獲取了 id 1 的course對象,並將它傳遞給course.html模版,模版代碼以下:
{ % for student in course.students. all % }
<p>{{ student.name }}< / p>
{ % endfor % }
首先經過course.students. all ,查尋到course對象關聯的students對象集,而後用 for 標籤循環它,獲取每一個student對象,再用student模型的定義,訪問其各個字段的屬性。
  
  
反向查詢:
從student往course查,假設有以下的視圖:
def test2(request):
     student = models.Student.objects.get(pk = 1 )
     return render(request, 'student.html' , locals ())
  
獲取了 id 1 的student對象,並將它傳遞給student.html模版,模版代碼以下:
{ % for course in  student.course_set. all % }
{{ course.name }}
{ % endfor % }
經過student.course_set. all ,反向獲取到student實例對應的全部course對象,而後再 for 標籤循環每一個course,調用course的各類字段屬性。
  
####
對於外鍵ForeignKey,其用法基本相似。只不過正向是obj.fk,且只有 1 個對像,不是集合。反向則是obj.fk_set,相似多對多。

8、內置模板標籤

標籤 說明
autoescape 自動轉義開關
block 塊引用
comment 註釋
csrf_token CSRF令牌
cycle 循環對象的值
debug 調試模式
extends 繼承模版
filter 過濾功能
firstof 輸出第一個不爲False的參數
for 循環對象
for … empty 帶empty說明的循環
if 條件判斷
ifequal 若是等於
ifnotequal 若是不等於
ifchanged 若是有變化,則..
include 導入子模版的內容
load 加載標籤和過濾器
lorem 生成無用的廢話
now 當前時間
regroup 根據對象重組集合
resetcycle 重置循環
spaceless 去除空白
templatetag 轉義模版標籤符號
url 獲取url字符串
verbatim 禁用模版引擎
widthratio 寬度比例
with 上下文變量管理器

9、內置過濾器總覽

爲模版過濾器提供參數的方式是:過濾器後加個冒號,再緊跟參數,中間不能有空格! 目前只能爲過濾器最多提供一個參數!django

過濾器 說明
add 加法
addslashes 添加斜槓
capfirst 首字母大寫
center 文本居中
cut 切除字符
date 日期格式化
default 設置默認值
default_if_none 爲None設置默認值
dictsort 字典排序
dictsortreversed 字典反向排序
divisibleby 整除判斷
escape 轉義
escapejs 轉義js代碼
filesizeformat 文件尺寸人性化顯示
first 第一個元素
floatformat 浮點數格式化
force_escape 強制馬上轉義
get_digit 獲取數字
iriencode 轉換IRI
join 字符列表連接
last 最後一個
length 長度
length_is 長度等於
linebreaks 行轉換
linebreaksbr 行轉換
linenumbers 行號
ljust 左對齊
lower 小寫
make_list 分割成字符列表
phone2numeric 電話號碼
pluralize 複數形式
pprint 調試
random 隨機獲取
rjust 右對齊
safe 安全確認
safeseq 列表安全確認
slice 切片
slugify 轉換成ASCII
stringformat 字符串格式化
striptags 去除HTML中的標籤
time 時間格式化
timesince 從什麼時候開始
timeuntil 到什麼時候多久
title 全部單詞首字母大寫
truncatechars 截斷字符
truncatechars_html 截斷字符
truncatewords 截斷單詞
truncatewords_html 截斷單詞
unordered_list 無序列表
upper 大寫
urlencode 轉義url
urlize url轉成可點擊的連接
urlizetrunc urlize的截斷方式
wordcount 單詞計數
wordwrap 單詞包裹
yesno 將True,False和None,映射成字符串‘yes’,‘no’,‘maybe’
相關文章
相關標籤/搜索