Django中模板的用法簡介 1. 模板系統的介紹 Django作為一個Web框架,其模板所需的HTML輸出靜態部分以及動態內容插入 模板由HTML代碼和邏輯控制代碼構成 Django框架的模板語言的語法格式: {{var_name}} 例如:HTML被直接編碼在python代碼中: import ...
Django中模板的用法簡介
1. 模板系統的介紹
Django作為一個Web框架,其模板所需的HTML輸出靜態部分以及動態內容插入
模板由HTML代碼和邏輯控制代碼構成
Django框架的模板語言的語法格式:
{{var_name}}
例如:HTML被直接編碼在python代碼中:
import datetime
def current_datetie(request):
time1 = datetime.datetime.now()
html="<html><body>the time is $s.</body></html>"%time1
return HttpResponse(html)
或者:
>>> python manange.py shell #進入該django項目的環境
>>> from django.template import Context,Template
>>> t1=Template("hello {{name}}.")
>>> c1=Context({"name":"world"})
>>> t1.render(c1)
'hello world.'
同一個模板,可以有多個上下文,就可以通過創建模板對象來渲染多個上下文
創建一個模板就可以多次調用render()方法渲染上下文
2 模板支持的語法
語法格式:
{{var_name}}
Django模板解析工作都是在後臺通過對正則表達式一次性調用來完成
2.1 深度的變數查找
python manage.py shell #進入Django項目環境終端
2.1.1 訪問列表索引
>>> from django.template import Template, Context
>>> t1 = Template('hello {{ items.2 }}.')
>>> c1 = Context({'items': ['linux', 'javascript', 'python']})
>>> t1.render(c1)
'hello python.'
2.1.2 訪問字典索引
>>> from django.template import Template,Context
>>> person = {"name":"Jack","age":22}
>>> t1 = Template("{{person.name}} is {{person.age}} years old.")
>>> c1 = Context({"person":person})
>>> t1.render(c1)
'Jack is 22 years old.'
2.1.3 datetime示例
>>> from django.template import Template,Context
>>> import datetime
>>> day1=datetime.datetime.utcnow()
>>> day1.year
2017
>>> day1.month
8
>>> day1.day
20
>>> t1=Template("the month is {{ date.month }} and the year is {{ date.year }}")
>>> c1=Context({"date":day1})
>>> t1.render(c1)
'the month is 8 and the year is 2017'
2.1.4 類的實例
>>> class Person(object):
... def __init__(self,first_name,second_name):
... self.first_name=first_name
... self.second_name=second_name
...
>>> t1=Template("hello,{{ person.first_name }}--{{ person.second_name }}.")
>>> c1=Context({"person":Person("Jack","Bones")})
>>> t1.render(c1)
'hello,Jack--Bones.'
2.1.5 引用對象方法
>>> from django.template import Template,Context
>>> t1 = Template("{{var}}--{{var.upper}}--{{var.isdigit}}")
>>> t1.render(Context({"var":"Hello"}))
'Hello--HELLO--False'
>>> t.render(Context({"var":"666"}))
'666--666--True'
註意點:
調用方法時並沒有使用圓括弧,而且也無法給該方法傳遞參數
2.2 變數的過濾器(filter的使用)
格式:
{{obj|filter:param}}
參數:
add 給變數加上相應的值
addslashes 給變數中的引號前加上斜線
capfirst 首字母大寫
cut 從字元串中移除指定的字元
date 格式化日期字元串
default 如果值是False,就替換成設置的預設值,否則就是用本來的值
default_if_none 如果值是None,就替換成設置的預設值,否則就使用本來的值
例子:
#value1="aBcDe"
{{ value1|upper }}#輸入為"ABCDE"
#value2=5
{{ value2|add:3 }}#輸入為8
#value3='he llo wo r ld'
{{ value3|cut:' ' }}#輸入為"helloworld"
#value4="hello world"
{{ value4|capfirst }}#輸入為"Hello world"
#import datetime
#value5=datetime.datetime.now()
{{ value5|date:'Y-m-d' }}#輸入為"2017-08-20"
#value6=[]
{{ value6 }}#輸入為"[]"
{{ value6|default:'空的' }} #輸入為"空的"
#value7='<a href="#">click</a>'
{{ value7 }}#輸入為"<a href="#">click</a>"
{{ value7|safe }}<br> # 如果不想標簽被渲染,加safe即可
{{ value7|striptags }}
{% autoescape off %} #Django安全機制關閉,標簽會被渲染
{{ value7 }}
{% endautoescape %}
#value8='1234'
{{ value8|filesizeformat }}
{{ value8|first }}
{{ value8|length }}
{{ value8|slice:":-1" }}
#value9='http://www.baidu.com/?a=1&b=3'
{{ value9|urlencode }}
value9='hello I am Tony'
標簽(tag)的使用(使用大括弧和百分比的組合來表示使用tag)
2.3 模板語言的控制語句
2.3.1 {% if %} 的使用
{% if %}標簽計算一個變數值,如果是“true”,即它存在、不為空並且不是false的boolean值,
系統則會顯示{% if %}和{% endif %}間的所有內容
例子:
{% if num >= 100 and 8 %}
{% if num > 200 %}
<p>num大於200</p>
{% else %}
<p>num大於100小於200</p>
{% endif %}
{% elif num < 100%}
<p>num小於100</p>
{% else %}
<p>num等於100</p>
{% endif %}
{% if %}標簽接受單個and,or或者not來測試多個變數值或者否定一個給定的變數
{% if %}標簽不允許同一標簽里同時出現and和or,否則會產生歧義
例如下麵的標簽是不合法的:
{% if obj1 and obj2 or obj3 %}
2.3.2 {% for %}的使用
{% for %}標簽按順序遍歷一個序列中的各個元素,每次迴圈模板系統都會渲染{% for %}和{% endfor %}之間的所有內容
例子:
<ul>
{% for obj in list %}
<li>{{ obj }}</li>
{% endfor %}
</ul>
可以在標簽里添加reversed來反序迴圈列表:
{% for obj in list reversed %}
...
{% endfor %}
{% for %}標簽可以嵌套:
{% for country in countries %}
<h1>{{ country.name }}</h1>
<ul>
{% for city in country.city_list %}
<li>{{ city }}</li>
{% endfor %}
</ul>
{% endfor %}
for迴圈不支持中斷迴圈,也不支持continue語句
{% for %}標簽內置了一個forloop模板變數,這個變數含有關於迴圈的屬性
forloop.counter 表示迴圈的次數,它從1開始計數
forloop.counter0 類似於forloop.counter,但它是從0開始計數
forloop.revcounter 反向遍歷整個列表,revcounter表示迴圈的次數,最後一次為1
forloop.revcounter0 反向遍歷整個列表,revcounter表示迴圈的次數,最後一次為0
forloop.first 返回一個布爾值,當第一次迴圈時值為True,其餘為False
例子:
{% for item in todo_list %}
<p>{{ forloop.counter }}: {{ item }}</p>
{% endfor %}
{% for object in objects %}
{% if forloop.first %}
<li class="first">
{% else %}
<li>
{% endif %}
{{ object }}</li>
{% endfor %}
forloop變數只能在迴圈中得到,當模板解析器到達{% endfor %}時forloop變數就會消失
如果模板context已經包含一個叫forloop的變數,Django會用{% for %}標簽替代它
Django會在for標簽的塊中覆蓋由開發人員定義的forloop變數的值
在其他非迴圈的地方,你的forloop變數仍然可用
2.3.3 {% empty %}
用法:
{{li }}
{% for i in li %}
<li>{{ forloop.counter0 }}----{{ i }}</li>
{% empty %}
<li>this is empty!</li>
{% endfor %}
2.3.4 {% csrf_token %} csrf_token標簽
用於生成csrf_token的標簽,用於防治跨站攻擊驗證
如果view的index里用的是render_to_response方法,則不會生效
其實這裡是生成一個input標簽,與其他表單標簽一起提交給後臺的
2.3.5 {% url %} #引用路由配置的地址
2.3.6 {% verbatim %} #禁止render
用法:
{% verbatim %} #hello標簽不會被模板渲染
{{ hello }}
{% endverbatim %}
2.3.7 {% load %} 載入標簽庫
2.3.8 自定義filter和simply_tag
1、在app中創建templatetags模塊
2、創建任意 .py 文件,如:my_tags.py
from django import template
from django.utils.safestring import mark_safe
register = template.Library() # register的名字是固定的,不可改變
@register.filter
def custom_filter(x,y):
return x*y
@register.simple_tag
def custom_simple(x,y,z):
return x+y+z
3、在使用自定義simple_tag和filter的html文件中導入之前創建的 my_tags.py :{% load my_tags %}
4、使用simple_tag和filter
-------------------------------HTML文件
{% load xxx %} # 位於首行,xxx代表自定義的文件名
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>Hello {{ user.0 }}</h1>
{{ user.3|custom_filter:8 }}
{% custom_simple user.3 2 3 %}
</body>
</html>
5、在settings中的INSTALLED_APPS配置當前app,不然django無法找到自定義的simple_tag
6、filter可以用在if等語句後,simple_tag不可以
{% if num|filter_multi:30 > 100 %}
{{ num|filter_multi:30 }}
{% endif %}
2.4 模板繼承
2.4.1 include(繼承)模板標簽
{% include %}是一個內建模板標簽,允許在模板中包含其它的模板內容.
標簽的參數是所要包含的模板的名稱,可以是一個變數,也可以是單/雙引號硬編碼的字元串.
每當在多個模板中出現相同的代碼時,就應該考慮是否要使用{% include %}來減少代碼重覆
2.4.2 extend(繼承)模板標簽
在一個大型網站中,有一些區域的內容始終是不變的,
減少共用頁面區域所引起的重覆和冗餘代碼Django框架中使用的方法就是模板繼承
本質上來說,模板繼承是先構造一個基礎框架模板,而後在其子模板中對公用部分和定義塊進行重載
母板:{% block title %}{% endblock %} # 定義盒子
子板:{% extends "base.html" %} # 繼承母板的內容,且必須放在模板第一行
{% block title %}{% endblock %} # 可以對盒子的內容進行修改
{% csrf_token %} # 取消csrf安全保護
{% black.super %}
{% include '小組件路徑' %} # HTML出現相同塊代碼時,新建公用小組件HTML文件
如果在模板中使用{% extends %},必須保證其為模板中的第一個模板標記,否則模板不會起作用
一般來說,基礎模板中的{% block %}標簽越多越好,子模板不必定義父模板中所有的代碼塊,
因此,可以用合理的預設值對一些代碼塊進行填充,然後只對子模板所需的代碼塊進行重定義.
如果多個模板之間的代碼重用太多,可以考慮將重覆代碼段放放到父模板的某個{% block %}中.
當需要訪問父模板中的塊的內容,使用{{ block.super }}標簽,這個魔法變數將會表現出父模板中的內容,
如果只想在上級代碼塊基礎上添加內容,而不是全部重載,這個魔法變數就非常有用了.
不允許在同一個模板中定義多個同名的{% block %}.
因為block標簽的工作方式是雙向的,block標簽定義了在父模板中{% block %}.
如果父模板中出現了兩個相同名稱的{% block %}標簽,父模板將無法使用哪個塊的內容