模板渲染的官方文檔css
關於模板渲染你只須要記兩種特殊符號(語法):html
在Django的模板語言中按此語法使用:{{ 變量名 }}。前端
當模版引擎遇到一個變量,它將計算這個變量,而後用結果替換掉它自己。 變量的命名包括任何字母數字以及下劃線 ("_")的組合。 變量名稱中不能有空格或標點符號。python
深度查詢據點符(.)在模板語言中有特殊的含義。當模版系統遇到點("."),它將以這樣的順序查詢:數據庫
字典查詢(Dictionary lookup)
屬性或方法查詢(Attribute or method lookup)
數字索引查詢(Numeric index lookup)django
注意事項:bootstrap
幾個例子:後端
view中代碼:瀏覽器
from django.shortcuts import render # Create your views here. def index(request): num = 100 name = 'anwen' lst = ['安文', 'didi'] # lst=[] dic = {'name': '安文', 'age': 23, 'hobby': '游泳'} class Animal(): def __init__(self): self.kind = 'dog' def eat(self): return 'chi' a = Animal() # xx='ll' filesize = '432511234.234' words = 'hello word i have a dream' tag = '<a href="http://www.baidu.com">百度</a>' import datetime time = datetime.datetime.now() # return render(request,'index.html',{'num':num,'name':name,'lst':lst,'dic':dic}) print(locals()) return render(request, 'index.html', locals())
模板index中支持的寫法:緩存
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <p>數字:{{ num }}</p> <p>字符串:{{ name }}</p> <p>列表:{{ lst }}</p> <p>{{ lst.2 }}</p> <p>字典:{{ dic }}</p> <p>{{ dic.name }}</p> <p>類方法:{{ a.eat }}</p> </body> </html>
在Django的模板語言中,經過使用 過濾器 來改變變量的顯示。
過濾器的語法: {{ value|filter_name:參數 }}
使用管道符"|"來應用過濾器。
例如:{{ name|lower }}會將name變量應用lower過濾器以後再顯示它的值。lower在這裏的做用是將文本全都變成小寫。
注意事項:
Django的模板語言中提供了大約六十個內置過濾器。
若是一個變量是false或者爲空,使用給定的默認值。 不然,使用變量的值。
<p>{{ xx|default:'啥都沒有' }}</p> #若是value沒有傳值或者值爲空的話就顯示啥都沒有
返回值的長度,做用於字符串和列表。
{{ value|length }}
返回value的長度,如 value=['a', 'b', 'c', 'd']的話,就顯示4.
{#獲取數據長度#} <p>{{ lst|length }}</p>
將值格式化爲一個 「人類可讀的」 文件尺寸 (例如 '13 KB'
, '4.1 MB'
, '102 bytes'
, 等等)。例如:
filesize = '432511234.234' <p>{{ filesize|filesizeformat }}</p> #若是filesize是432511234.234,輸出將會是412.5 MB
切片,若是 value="hello world",還有其餘可切片的數據類型
{#切片,若是 value="hello world",還有其餘可切片的數據類型#} <p>{{ words|slice:'6:10' }}</p>
格式化,若是 value=datetime.datetime.now()
{{ value|date:"Y-m-d H:i:s"}} 關於時間日期的可用的參數(除了Y,m,d等等)還有不少,有興趣的能夠去查查看看。
若是字符串字符多於指定的字符數量,那麼會被截斷。截斷的字符串將以可翻譯的省略號序列(「...」)結尾。
參數:截斷的字符數
words = 'hello word i have a dream' {{ words|truncatechars:9}} #注意:最後那三個省略號也是9個字符裏面的,也就是這個9截斷出來的是6個字符+3個省略號,有人會說,怎麼展開啊,配合前端的點擊事件就行啦
在必定數量的字後截斷字符串,是截多少個單詞。
例如:‘hello word i have a dream’,
{{ value|truncatewords:3}} #上面例子獲得的結果是 'hello word i...'
移除value中全部的與給出的變量相同的字符串
hello word i have a dream {{ value|cut:' ' }} #hellowordihaveadream
使用字符串鏈接列表,{{ list|join:', ' }},就像Python的str.join(list)
lst = ['安文', 'didi','yage'] <p>{{ lst|join:'+' }}</p> #安文+didi+yage
標籤看起來像是這樣的: {% tag %}
。標籤比變量更加複雜:一些在輸出中建立文本,一些經過循環或邏輯來控制流程,一些加載其後的變量將使用到的額外信息到模版中。一些標籤須要開始和結束標籤 (例如{% tag %} ...
標籤 內容 ... {% endtag %})。
遍歷每個元素: 寫個for,而後 tab鍵自動生成for循環的結構,循環很基礎,就這麼簡單的用,沒有什麼break之類的,複雜一些的功能,你要經過js
{% for l in lst %} <p>{{ forloop.counter }}{{ l }}</p> <!--凡是變量都要用兩個大括號括起來--> <!--for ... empty--> <!--for 標籤帶有一個可選的{% empty %} 從句,以便在給出的組是空的或者沒有被找到時,能夠有所操做。--> {% empty %} <p>no</p> {% endfor %} {#遍歷一個字典#} {% for key,value in dic.items %} <p>{{ key }}--{{ value }}</p> {% endfor %}
注:循環序號能夠經過{{forloop}}顯示,必須在循環內部用
forloop.counter 當前循環的索引值(從1開始),forloop是循環器,經過點來使用功能 forloop.counter0 當前循環的索引值(從0開始) forloop.revcounter 當前循環的倒序索引值(從1開始) forloop.revcounter0 當前循環的倒序索引值(從0開始) forloop.first 當前循環是否是第一次循環(布爾值) forloop.last 當前循環是否是最後一次循環(布爾值) forloop.parentloop 本層循環的外層循環的對象,再經過上面的幾個屬性來顯示外層循環的計數等
{% if %}
會對一個變量求值,若是它的值是「True」(存在、不爲空、且不是boolean類型的false值),對應的內容塊會輸出。if語句支持 and 、or、==、>、<、!=、<=、>=、in、not in、is、is not判斷,注意條件兩邊都有空格。
{% if num > 100 %} <p>大於100</p> {% elif num < 100 %} <p>小於100</p> {% else %} <p>等於100</p> {% endif %}
{#Django的模板語言不支持連續判斷,即不支持如下寫法:#} {#{% if a > b > c %}#} {#...#} {#{% endif %}#}
使用一個簡單地名字緩存一個複雜的變量,多用於給一個複雜的變量起別名,當你須要使用一個「昂貴的」方法(好比訪問數據庫)不少次的時候是很是有用的
例如:
注意等號左右不要加空格。
{% with dic.hobby as hb %} <p>{{ hb }}</p> {% endwith %} {#注意:等號左右不要加空格。#} {% with hb=dic.hobby %} <p>{{ hb }}</p> {% endwith %}
咱們以post方式提交表單的時候,會報錯,還記得咱們在settings裏面的中間件配置裏面把一個csrf的防護機制給註銷了啊,自己不該該註銷的,而是應該學會怎麼使用它,而且不讓本身的操做被forbiden,經過這個東西就能搞定。
這個標籤用於跨站請求僞造保護,
在頁面的form表單裏面(注意是在form表單裏面)任何位置寫上{% csrf_token %},這個東西模板渲染的時候替換成了,隱藏的,這個標籤的值是個隨機字符串,提交的時候,這個東西也被提交了,首先這個東西是咱們後端渲染的時候給頁面加上的,那麼當你經過我給你的form表單提交數據的時候,你帶着這個內容我就認識你,不帶着,我就禁止你,由於後臺咱們django也存着這個東西,和你這個值相同的一個值,能夠作對應驗證是否是我給你的token,存儲這個值的東西咱們後面再學,你先知道一下就好了,就像一個咱們後臺給這個用戶的一個通行證,若是你用戶沒有按照我給你的這個正常的頁面來post提交表單數據,或者說你沒有先去請求我這個登錄頁面,而是直接模擬請求來提交數據,那麼我就能知道,你這個請求是非法的,反爬蟲或者惡意攻擊個人網站,之後將中間件的時候咱們在細說這個東西,可是如今你要明白怎麼回事,明白爲何django會加這一套防護。
爬蟲發送post請求簡單模擬:
import requests res = requests.post('http://127.0.0.1:8000/login/',data={ 'username':'chao', 'password':'123' }) print(res.text)
csrf_token繞過csrf的防護機制
#views.py from django.shortcuts import render def token(request): return render(request, 'token.html')
<!--token.html--> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>token</title> </head> <body> <form action="" method="post"> {% csrf_token %} 用戶名: <input type="text" name="username"> <button>提交</button> </form> </body> </html>
Django模版引擎中最強大也是最複雜的部分就是模版繼承了。模版繼承可讓您建立一個基本的「骨架」模版,它包含您站點中的所有元素,而且能夠定義可以被子模版覆蓋的 blocks 。
from django.conf.urls import url from django.contrib import admin from app01 import views urlpatterns = [ url(r'^admin/', admin.site.urls), # 模板 url(r'^base/', views.base), url(r'^menu1/', views.menu1), url(r'^menu2/', views.menu2), url(r'^menu3/', views.menu3), ]
#views.py from django.shortcuts import render def base(request): #模板函數 return render(request, 'base.html') #模板頁面 def menu1(request): return render(request, 'menu1.html') def menu2(request): return render(request, 'menu2.html') def menu3(request): return render(request, 'menu3.html')
<!--menu1.html--> {% extends 'base.html' %} {% block content %} menu1 {% endblock %} <!--menu2.html--> {% extends 'base.html' %} {% block content %} menu2 {% endblock %} <!--menu3.html--> {% extends 'base.html' %} {% block content %} menu3 {% endblock %}
能夠將經常使用的頁面內容如導航條,頁尾信息等組件保存在單獨的文件中,而後在須要使用的地方,文件的任意位置按以下語法導入便可。
{% include 'navbar.html' %}
#urls.py from django.conf.urls import url from django.contrib import admin from app01 import views urlpatterns = [ url(r'^admin/', admin.site.urls), # 組件nav url(r'^nav/', views.nav), url(r'^newnav/', views.nav), ]
#views.py from django.shortcuts import render def nav(request): return render(request,'nav.html') def newnav(request): return render(request,'newnav.html')
有個以下的導航欄,nav.html
<!--nav.html--> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>nav</title> <style> body { margin: 0; padding: 0; } .nav { background: red; height: 40px; } </style> </head> <body> <div class="nav"> <a href="">導航</a> <a href="">導航</a> <a href="">導航</a> <a href="">導航</a> <input type="text"> <button>搜索</button> </div> </body> </html>
用了組件的newnav.html
<!--newnav.html--> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> {# 組件#} {#能夠將經常使用的頁面內容如導航條,頁尾信息等組件保存在單獨的文件中,而後在須要使用的地方,文件的任意位置按以下語法導入便可。#} {% include 'nav.html' %} </body> </html>
組件是提供某一完整功能的模塊,如:編輯器組件,QQ空間提供的關注組件 等。 而插件更傾向封閉某一功能方法的函數。 這二者的區別在 Javascript 裏區別很小,組件這個名詞用得很少,通常統稱插件。
1. app應用文件夾中建立一個templatetags文件件,必須是這個名字 2. templatetags文件夾中建立一個 filtertest.py文件,文件名字隨便起 3. 建立自定義過濾器 from django import template # register的名字是固定的,不可改變,註冊器 register = template.Library() # @register.filter # def filter(v1): #一個參數 # v = v1 + 'yage' # return v @register.filter def filter(v1, v2): # 兩個參數 v = v1 + 'yage' + v2 return v 4. 使用 html文件中 {% load 文件名 %} {% load filtertest %} {#一個參數#} {{ v1|filter }} {#兩個參數#} {{ v1|filter:' nihao' }} 5. 注意:# filter參數有限制,最多兩個參數
1. app應用文件夾中建立一個templatetags文件件,必須是這個名字 2. templatetags文件夾中建立一個 xx.py文件,文件名字隨便起 3. 建立自定義標籤 from django import template # register的名字是固定的,不可改變,註冊器 register = template.Library() # simple_tag和自定義filter相似,只不過接收更靈活的參數,沒有個數限制。 # 注意:filter能夠用在if、for等語句後,simple_tag不能夠 @register.simple_tag def simple_tag(vv): v = 'yagehaha' + vv return v 4. 使用 html文件中 {% load 文件名 %} {#simple_tag標籤#} <p>{% simple_tag v1 %}</p> 5. #能夠傳多個參數
1. app應用文件夾中建立一個templatetags文件件,必須是這個名字 2. templatetags文件夾中建立一個 xx.py文件,文件名字隨便起 3. 建立自定義inclusion_tag # 多用於返回html代碼片斷 做爲一個組件 @register.inclusion_tag('inclusion_tag.html') # 將inclusion_tag.html裏面的內容用下面函數的返回值渲染,而後做爲一個組件同樣,加載到使用這個函數的html文件裏面 def inclusion_tag(ll): # 參數能夠傳多個進來 return {'date': ll} # 這裏能夠穿多個值,和render的感受是同樣的{'data1':data1,'data2':data2....} # views 的 ll 傳給 index.html 中的{% inclusion_tag ll%}, # inclusion_tag 接收參數到filtertest.py 的 def inclusion_tag(ll), # 將參數ll傳給@register.inclusion_tag('inclusion_tag.html') 進行模板渲染。 4.使用 {% inclusion_tag ll%}
js、css、img等都叫作靜態文件,那麼關於django中靜態文件的配置,咱們就須要在settings配置文件裏面寫上這寫內容:
1 在項目中建立一個文件夾,好比叫jingtaiwenjian # STATIC_URL = '/xxx/' #別名,隨便寫名字,可是若是你更名字,別忘了前面頁面裏面若是你是經過/xxx/bootstrap.css的時候,若是這裏的別名你改爲了/static/的話,你前端頁面的路徑要改爲/static/bootstrap.css。因此咱們都是用下面的load static的方式來使用靜態文件路徑 2 STATIC_URL = '/static/' #別名 3 STATICFILES_DIRS = [ os.path.join(BASE_DIR,'jingtaiwenjian'), #注意別忘了寫逗號,第二個參數就是項目中你存放靜態文件的文件夾名稱 ]
目錄:別名也是一種安全機制,瀏覽器上經過調試臺你可以看到的是別名的名字,這樣別人就不能知道你靜態文件夾的名字了,否則別人就能經過這個文件夾路徑進行攻擊。
前端頁面引入靜態文件的寫法,由於別名也可能會修改,因此使用路徑的時候經過load static來找到別名,經過別名映射路徑的方式來獲取靜態文件
{% 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>
{% 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!" />