一、概要
對于模版,其實就是讀取模版(其中嵌套著模版標簽),然后將模型中獲取的數據插入到模版中,最后將信息返回給用戶。
二、模板應用
1、說明
只要是在html里面有模板語法就不是html文件了,這樣的文件就叫做模板
本質就是html+模板語法
2、為什么要使用模板
- 對頁面設計進行的任何改變都必須對 Python 代碼進行相應的修改。 網站設計的修改往往比底層 Python 代碼的修改要頻繁得多,因此如果可以在不進行 Python 代碼修改的情況下變更設計,那將會方便得多。
- Python 代碼編寫和 HTML 設計是兩項不同的工作,大多數專業的網站開發環境都將他們分配給不同的人員(甚至不同部門)來完成。 設計者和HTML/CSS的編碼人員不應該被要求去編輯Python的代碼來完成他們的工作。
- 程序員編寫 Python代碼和設計人員制作模板兩項工作同時進行的效率是最高的,遠勝于讓一個人等待另一個人完成對某個既包含 Python又包含 HTML 的文件的編輯工作。
2、基本使用
- views.py
class User: def __init__(self, name=None, age=0): self.name = name self.age = age # views def index(request): title = "Hello Django" num = 110 li = [1, 2, 3, 4, 5] dic = {'name': '小明', 'age': 20} user1 = User(name='小明') user2 = User(name='小紅') user_list = [user1, user2] context = { 'num': num, 'title': title, 'li': li, 'dic': dic, 'user': user1, 'user_list': user_list, } return render(request, 'home/index.html', context)
- templates/home/index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="/static/js/jquery-3.3.1.js"></script> </head> <body> <ul> <li>數字:{{ num }}</li> <li>字符串:{{ title }}</li> <li>列表:{{ li.0 }}</li> <li>列表:{{ li.1 }}</li> <li>列表:{{ li.2 }}</li> <li>字典:{{ dic.name }}</li> <li>字典:{{ dic.age }}</li> <li>對象:{{ user.name }}</li> <li>對象:{{ user.age }}</li> <li>列表:{{ user_list.1.name }}</li> </ul> <h3>遍歷li的值</h3> {% for item in li %} <p>{{ item }}</p> {% endfor %} <h3>遍歷列表,去對象的值</h3> {% for user in user_list %} 用戶名:<span>{{ user.name }}</span> 密碼:<span>{{ user.age }}</span> {% endfor %} <h3>遍歷字典,</h3> {% for user in dic.items %} 用戶名:<span>{{ user.name }}</span> 密碼:<span>{{ user.age }}</span> {% endfor %} <h3>遍歷列表,去對象的值: 倒序</h3> {% for user in user_list reversed %} 用戶名:<span>{{ user.name }}</span> 密碼:<span>{{ user.age }}</span> {% endfor %} </body> </html>
三、模板語法
1、變量--{}
1.1、 {}語法
- 語法格式
{{ }}
- 舉個栗子
#views.py def index(request): return render(request, 'home/index.html', {'content','模板語法'})
<body> <p>{{ content }}</p> </body>
1.2、語法
- 語法格式
對象.變量名
- 應用
字典查詢(Dictionary lookup) 屬性或方法查詢(Attribute or method lookup) 數字索引查詢(Numeric index lookup) 對象.方法名(必須無參)
- 舉個栗子
見基本
2、標簽--{% tag %}
標簽看起來像是這樣的:
{% tag %}
。標簽比變量更加復雜:一些在輸出中創建文本,一些通過循環或邏輯來控制流程,一些加載其后的變量將使用到的額外信息到模版中。一些標簽需要開始和結束標簽 (例如
{% tag %} ...
標簽 內容 ... {% endtag %})
2.1、for
- 語法格式1
{% for 元素 in 可迭代對象 %} {{ 元素 }} {% endfor %} {% for 元素 in 可迭代對象 %} {{ 元素. 屬性}} {% endfor %}
- 語法格式2
{% for 元素 in 可迭代對象 reversed%} {{ 元素. 屬性}} {% endfor %}
- 語法格式3
{% for 元素 in 可迭代對象 %} <p>{{元素.屬性}}</p> {% empty %} <p>空元素</p> {% endfor %}
- 語法格式4
{% for item in 可迭代對象 %} # 默認從1開始計數 {{ forloop.counter }} # 表示從0開始計數 {{ forloop.counter0 }} # {{ forloop.recounter }} {{ forloop.recounter0 }} # 判斷是否是第一個元素 {{ forloop.first }}: {{ item }} # 判斷是否是最后一個元素 {{ forloop.last }}: {{ item }} {% endfor %}
- 示例代碼
{% for item in li %} <h3>計算器</h3> 計數默認:<span>{{ forloop.counter0 }}</span> 計數倒序:<span>{{ forloop.revcounter }}</span> 是否第一項:<span>{{ forloop.first }}</span> 是否是最后一項:<span>{{ forloop.last }}</span> {% endfor %}
{% for link in links %} {{ link }} {% if not forloop.last %} | {% endif %} {% endfor %}
2.2、if
- 語法格式
{% if 條件表達式1 %} {% elif 條件表達式2 %} {% else %} {% endif %}
- 示例代碼
{% if num > 100 or num < 0 %} <p>無效</p> {% elif num > 80 and num < 100 %} <p>優秀</p> {% else %} <p>差</p> {% endif %}
2.3、csrf_token
- 說明
用于生成csrf_token的標簽,用于防治跨站攻擊驗證。注意如果你在view的index里用的是render_to_response方法,不會生效。其實,這里是會生成一個input標簽,和其他表單標簽一起提交給后臺的。
注意:在settings中的中間件MIDDLEWARE中配置打開
'django.middleware.csrf.CsrfViewMiddleware', - 語法格式
{%csrf_token%}
- 示例代碼
<form action="{% url "bieming"%}" > <input type="text"> <input type="submit"value="提交"> {%csrf_token%} </form>
2.4、url
- 說明
引用路由配置的地址 - 語法格式
{% url 'name' %}
- 舉個栗子
url的用法也很簡單,只要在urlpatterns里使用它,附加一個name urlpatterns = [ url(r'^home$','index' ,name="test_url"), ]
<a href="{% url 'test_url' %}"></a>
2.5、static
- 說明
引用靜態文件 - 使用步驟
1、在首部使用模板標簽{% load staticfiles %}來說明一下內容,將載入靜態文件;
2、使用{% static 'css/style.css' %}來指明CSS框架文件的存放位置;
3、若html文件中,出現需要引用靜態文件的地方,都需要用static來替換。 - 示例代碼
<!DOCTYPE html> <html lang="en"> {% load staticfiles %} <head> <meta charset="UTF-8"> <title>Title</title> <link href="{% static 'css/common.css'%}" rel='stylesheet'> <script src="{% static 'js/jquery-3.3.1.js'%}"></script> </head> <body> </body> </html>
模板標簽
- 說明
該標簽允許在(模板中)包含其它的模板的內容。 標簽的參數是所要包含的模板名稱,可以是一個變量,也可以是用單/雙引號的字符串。 每當在多個模板中出現相同的代碼時,就應該考慮是否要使用 {% include %} 來減少重復。 - 語法
{% include '引入的模板名' %}
- 示例代碼
top.html <div> <a href="{% url 'login' %}">請登錄</a> <a href="{% url 'register' %}">免費注冊</a> </div>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> {% include 'top.html' %} </body> </html>
3、過濾器 {{obj|filter__name:param}}
可以通過過濾器來修改變量的顯示,過濾器的形式是:{{ variable | filter }},管道符號'|'代表使用過濾器
過濾器能夠采用鏈式的方式使用,例如:{{ text | escape | linebreaks }}
過濾器還可以帶參數,例如: {{ bio|truncatewords:30 }}
過濾器的參數中如果帶有空格,那么需要用引號引起來,例如:{{ list | join : ", "}}
django中30個內建的過濾器
3.1、add
- 說明
給變量加上相應的值
過濾器首先會強制把兩個值轉換成Int類型。如果強制轉換失敗, 它會試圖使用各種方式吧兩個值相加。它會使用一些數據類型 (字符串, 列表, 等等.) - 語法格式
{{ value|add:"值" }}
- 舉個栗子
#st = 'hello' {{ st|add:"world" }}
3.2、default
- 說明
如果一個變量是False或者為空,使用給定的默認值。否則,使用變量的值 - 語法格式
{{ value|default:",默認值" }}
- 舉個栗子
title = '' {{ title|default:",默認值" }}
3.3、length
- 說明
返回值的長度。它對字符串和列表都起作用 - 語法格式
{{ value|length }}
- 舉個栗子
li = ['a', 'b', 'c', 'd'] {{ li|length }} #4
3.5、date
- 說明
按指定的格式字符串參數格式化 date 或者 datetime 對象 - 語法格式
{{ value|date:"日期格式" }}
- 舉個栗子
#如果 now_time = datetime.datetime.now() {{ now_time|date:"Y-m-d H:i:s" }}
4、自定過濾器
4.1、說明
在內置的方法滿足不了我們的需求的時候,就需要自己定義屬于自己的方法了,自定義方法分別分為filter和simple_tag
4.2 、區別
- 傳參:
- filter默認最多只支持2個參數:可以用{{value|fun:"p1, p1, p3" }}這種形式將參數傳遞個函數
- simple_tag支持多個參數:{% fun p1 p2 p3 p4 %} 有多少就寫多少
- 模板語言if條件:
- filter支持if
# 函數的結果作為if語句的條件 {% if value|f1 %} <h1>True</h1> {% else %} <h1>False</h1>
- simple_tag: 不支持模板語言if條件`
4.3、步驟
- 在settings中的INSTALLED_APPS,注冊app
- 在app中創建templatetags目錄,目錄名必須為templatetags
- 創建一個自定義的custom_tags.py
from django import template from django.utils.safestring import mark_safe # register的名字是固定的,不可改變 register = template.Library() # 過濾器 @register.filter def test_filter(value, param): return value + param @register.filter def test_filter2(value, param1,param2): return value + param1 + param2 # 標簽 @register.simple_tag def multi_tag(value, p2, p3, p1): return value * p2 * p3 * p1 @register.simple_tag # 標簽 def my_input(id, arg): result = "<input type='text' id='%s' class='%s' />" % (id, arg,) return mark_safe(result)
- 在使用自定義simple_tag和filter的html文件中導入之前創建的 custom_tags.py
- 在引用模板中導入:{% load custom_tags %}
- 在模板中使用
{# 使用filter方式調用自定義方法 #} <!-- 將當做參數傳遞給test_filter1函數進行處理 處理方式 test_filter2(test_filter1) --> <p>{{ test_filter1|test_filter2}}</p> !-- 將test_filter當做參數傳遞給test_filter2函數進行處理,接受2個參數 處理方式 <p>{{ test_filter1|test_filter2:"xxx" }}</p> {# 使用simple_tag方式調用自定義方法 #} <!-- 將k1當做參數傳遞給multi_tag函數進行處理,接收多個參數 處理方式 multi_tag("處理的值", "參數1" "參數2" "參數3") --> <p>{% multi_tag "處理的值" "參數1" "參數2" "參數3" %}</p>
四、模版繼承
1、說明
Django模版引擎中最強大也是最復雜的部分就是模版繼承了。模版繼承可以讓您創建一個基本的“骨架”模版,它包含您網站中的全部元素,并且可以定義能夠被子模版覆蓋的塊
2、相關語法
- 繼承語法
{% extends "母版名稱" %}
- 塊語法
{% block 塊名稱 %} 重寫內容 {% endblock %}
3、示例代碼
- 母版
<!DOCTYPE html> <html lang="en"> {% load staticfiles %} <head> <meta charset="UTF-8"> <title> {% block page_title %} {% endblock %} </title> {% block page_css %} {% endblock %} {% block page_jq %} {% endblock %} </head> <body> <div> <div id="head"> {% block page_head %} {% endblock %} </div> <div id="content"> {% block page_content %} {% endblock %} </div> <div id="footer"> {% block page_footer %} {% endblock %} </div> </div> </body> </html>
- 子模板
{% extends 'base.html' %} {% block page_jq %} jq代碼 {% endblock %} {% block page_head %} 頭部HTML代碼 {% endblock %} {% block page_content %} 主體HTML內容代碼 {% endblock %} {% block page_footer %} 底部HTML內容代碼 {% endblock %}
4、總結
- 如果你在模版中使用 {% extends %} 標簽,它必須是模版中的第一個標簽。其他的任何情況下,模版繼承都將無法工作。
- 在base模版中設置越多的 {% block %} 標簽越好。請記住,子模版不必定義全部父模版中的blocks,所以,你可以在大多數blocks中填充合理的默認內容,然后,只定義你需要的那一個。多一點鉤子總比少一點好。
- 如果你發現你自己在大量的模版中復制內容,那可能意味著你應該把內容移動到父模版中的一個 {% block %} 中。
- 如果需要獲取父模板中的block 的內容,可以使用{{ block.super }} 變量。如果你想要在父block 中新增內容而不是完全覆蓋它,它將非常有用。