04 Django之模板系统
一.語法
關于模板渲染只需要記住兩種特殊符號(語法):
{{ }} 和 {% %}? (變量相關用{{ }}? 邏輯相關用{% %})
二.變量
在Django的模板語言中按照{{ 變量名 }}來使用.
當模板引擎遇到一個變量,它將計算這個變量,然后用結果替換掉它的本身
注意事項
1.如果計算結果的值是可調用的,它將被無參數的調用.調用的結果將成為模板的值.
2.如果使用的變量不存在,模板系統將插入string_if_invalid選項的值,它被默認設置為"(空字符串)"
例子:
views.py? 中的代碼
def index(request):import datetimes = "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 = namedef 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文件進行模板渲染,
如果你圖省事,你可以用它,但是很多多余的變量也被傳進去了,效率低
模板中的寫法:
<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的模板語言中,通過使用 過濾器來改變變量的顯示.
過濾器的語法: {{ vlaue|filter_name:參數}}
使用管道符來應用過濾器
例如:{{ name|lower }} 會將name變量應用lower過濾器之后再顯示它的值.lower的作用是將文本全部變成小寫.
注意事項:
default?
如果一個變量是false或者為空,使用給定的默認值,否則,使用變量的值
{{ value|default:"nothing"}}如果value沒有傳值或者值為空的時候就顯示nothing
length
返回值的長度,作用于字符串和列表.
{{ value|length}}
返回value的長度,如value=['a',?'b',?'c',?'d']的話,就顯示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"}}關于時間日期的可用的參數(除了Y,m,d等等)還有很多
safe
Django的模板中在進行模板渲染的時候會對HTML標簽和JS等語法標簽進行自動轉義,原因顯而易見,這樣是為了安全,django擔心這是用戶添加的數據,比如如果有人給你評論的時候寫了一段js代碼,這個評論一提交,js代碼就執行啦,這樣你是不是可以搞一些壞事兒了,寫個彈窗的死循環,那瀏覽器還能用嗎,是不是會一直彈窗啊,這叫做xss攻擊,所以瀏覽器不讓你這么搞,給你轉義了。但是有的時候我們可能不希望這些HTML元素被轉義,比如我們做一個內容管理系統,后臺添加的文章中是經過修飾的,這些修飾可能是通過一個類似于FCKeditor編輯加注了HTML修飾符的文本,如果自動轉義的話顯示的就是保護HTML標簽的源文件。為了在Django中關閉HTML的自動轉義有兩種方式,如果是一個單獨的變量我們可以通過過濾器“|safe”的方式告訴Django這段代碼是安全的不必轉義。
我們去network那個地方看看,瀏覽器看到的都是渲染之后的結果,通過network的response的那個部分可以看到,這個a標簽全部是特殊符號包裹起來的,并不是一個標簽,這都是django搞得事情。
比如:
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:' ' }}join
使用字符串連接列表,{{ list|join:', ' }},就像Python的str.join(list)
四 標簽Tags
標簽看起來像是{% tag %}. 標簽比變量更復雜:一些在輸出中創建文本,一些通過循環或邏輯來控制流程,一些加載其后的變量將使用到的額外信息到模板中.一些標簽需要開始和結束標簽(例如{% tag %} ...標簽 內容 ... {% endtag %})。
? for標簽
遍歷每一個元素:寫一個for,然后tab鍵自動生成for循環的結構,沒有break之類的,復雜一些的功能,需要通過js
{% for person in person_list %}<p>{{ person.name }}<p> <!--凡是變量就都要用兩個大括號括起來-->{% endfor %}
? 可以利用{%?for?obj?in?list?reversed?%}反向完成循環。
遍歷字典
{% for key,val in dic.items %}<p>{{ key }}:{{ val }}<p> {% endfor %}注:循環序號可以通過{{forloop}}顯示,必須在循環內部用
forloop.counter 當前循環的索引值(從1開始),forloop是循環器,通過點來使用功能 forloop.counter0 當前循環的索引值(從0開始) forloop.revcounter 當前循環的倒序索引值(從1開始) forloop.revcounter0 當前循環的倒序索引值(從0開始) forloop.first 當前循環是不是第一次循環(布爾值) forloop.last 當前循環是不是最后一次循環(布爾值) forloop.parentloop 本層循環的外層循環的對象,再通過上面的幾個屬性來顯示外層循環的計數等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的防御機制給注銷了啊,本身不應該注銷的,而是應該學會怎么使用它,并且不讓自己的操作被forbiden,通過這個東西就能搞定。
這個標簽用于跨站請求偽造保護
? 在頁面的form表單里面(注意是在form表單里面)任何位置寫上{% csrf_token %},這個東西模板渲染的時候替換成了<input type="hidden" name="csrfmiddlewaretoken" value="8J4z1wiUEXt0gJSN59dLMnktrXFW0hv7m4d40Mtl37D7vJZfrxLir9L3jSTDjtG8">,隱藏的,這個標簽的值是個隨機字符串,提交的時候,這個東西也被提交了,首先這個東西是我們后端渲染的時候給頁面加上的,那么當你通過我給你的form表單提交數據的時候,你帶著這個內容我就認識你,不帶著,我就禁止你,因為后臺我們django也存著這個東西,和你這個值相同的一個值,可以做對應驗證是不是我給你的token,存儲這個值的東西我們后面再學,你先知道一下就行了,就像一個我們后臺給這個用戶的一個通行證,如果你用戶沒有按照我給你的這個正常的頁面來post提交表單數據,或者說你沒有先去請求我這個登陸頁面,而是直接模擬請求來提交數據,那么我就能知道,你這個請求是非法的,反爬蟲或者惡意攻擊我的網站,以后將中間件的時候我們在細說這個東西,但是現在你要明白怎么回事,明白為什么django會加這一套防御。
?五 模板繼承
Django模板引擎中最強大的也是最復雜的部分就是模板繼承.模板繼承可以讓你創建一個基本的骨架模板,它包含您站點的全部元素,并且可以定義能夠被子木板覆蓋的blocks.
<!DOCTYPE html> <html lang="en"> <head><link rel="stylesheet" href="style.css" /><title>{% block title %}My amazing site{%/span> 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>對標簽設置id屬性? 然后{% block id屬性名字%}
?
這個模版,我們把它叫作?base.html, 它定義了一個可以用于兩列排版頁面的簡單HTML骨架。“子模版”的工作是用它們的內容填充空的blocks。
在這個例子中,?block?標簽定義了三個可以被子模版內容填充的block。?block?告訴模版引擎: 子模版可能會覆蓋掉模版中的這些位置。
子模版可能看起來是這樣的:
{% 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
請注意,子模版并沒有定義?sidebar?block,所以系統使用了父模版中的值。父模版的?{% block %}?標簽中的內容總是被用作備選內容(fallback)。
這種方式使代碼得到最大程度的復用,并且使得添加內容到共享的內容區域更加簡單,例如,部分范圍內的導航。
這里是使用繼承的一些提示:
-
如果你在模版中使用?{% extends %}?標簽,它必須是模版中的第一個標簽。其他的任何情況下,模版繼承都將無法工作,模板渲染的時候django都不知道你在干啥。
-
在base模版中設置越多的?{% block %}?標簽越好。請記住,子模版不必定義全部父模版中的blocks,所以,你可以在大多數blocks中填充合理的默認內容,然后,只定義你需要的那一個。多一點鉤子總比少一點好。
-
如果你發現你自己在大量的模版中復制內容,那可能意味著你應該把內容移動到父模版中的一個?{% block %}?中。
-
為了更好的可讀性,你也可以給你的?{% endblock %}?標簽一個?名字?。例如:
? 在大型模版中,這個方法幫你清楚的看到哪一個 ?{% block %}?標簽被關閉了。
- 不能在一個模版中定義多個相同名字的?block?標簽。
六 組件
可以將常用的頁面如導航條,頁尾信息等組件保存在單獨的文件中,然后在需要使用的地方,文件的任意位置按如下語法導入即可
{% include 'navbar.html' %}例如:有個如下的導航欄,nav.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.html
<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><title>Title</title> </head> <body> {% include 'nav.html' %} <h1>xxxxxxxxxx</h1> </body> </html>?七 自定義標簽和過濾器
1. 在setting中的INSTALLED_APPS配置當前的app,不然django無法找到自定義的simple_tag
2.在app中創建templatetags模塊(模塊只能是templatetags)
3.創建任意.py文件
from django import template from django.untils.safestring import mark_saferegister = template.Library() #register的名字是固定的,不可以改變@register.filter def filter_multi(v1,v2):return v1*v2@register.simple_tag #和自定義filter類似,只不過接受更靈活的參數,沒有個數限制def simple_tag_multi(v1,v2):return v1*v2@registe.simple_tag def my_input(id,arg):result = "<input type='text' id='%s' class='%s' />" %(id,arg,)return mark_safe(result)4. 在使用自定義simple_tag和filter的html文件中導入之前創建的my_tags.py
{% load my_tags%}5 使用simple_tag和filter(如何調用)
-------------------------------------------------------------.html {% load xxx%}#num = 12 {{ num|filter_muti:2}} #24{{ num|filter_multi:"[22,333,4444]"}}{{% simple_tag_multi 2 5 %}} 參數不限,但是不能放for 和 if循環 {% simple_tag_multi num 5 %}注意:filter可以用在if.for等語句后,simple_tag不可以
{% if num|filter_multi:30 > 100 %}{{ num|filter_multi:30 }} {% endif %}inclusion_tag
多用于返回html代碼片段
示例:
templatetags/my_inclusion.py
from django import templateregister = template.Library()@register.inclusion_tag('result.html') #將result.html里面的內容用下面函數的返回值渲染,然后作為一個組件一樣,加載到使用這個函數的html文件里面 def show_result(n):#參數可以傳多個進來n = 1 if n < 1 else int(n)data = ["第{}項".format(i) for i in range(1,n+1)]return {"data":data} #這里可以傳多個值,和render的感覺是一樣的 {'deta1':data1,
'data2':data2.....}
templates/snippets/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 inclusion_tag_test %}{% show_results 10 %} </body> </html>
?
轉載于:https://www.cnblogs.com/a2534786642/p/10444934.html
總結
以上是生活随笔為你收集整理的04 Django之模板系统的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 10774: matrix
- 下一篇: java信息管理系统总结_java实现科