Django(三)模板
1 簡介
1.1 什么是模板
視圖函數的作用是生成請求的響應,這種響應通常就是用戶所看到的html網頁。模板就是帶有模板語法({{ }}, {% %})的html文件,它能接收視圖函數傳遞的變量,通過模板引擎,模板被渲染成html頁面。
1.2 語法
在模板中,使用{{ }}結構表示一個變量,它是一種特殊的占位符,告訴模板引擎,這個位置的值從渲染模板時傳入的變量獲取;使用{% %}結構渲染標簽(控制結構)。
1.3模板查找機制
模板一般放在應用下的templates文件夾,Django的模板渲染引擎會自動查找所有應用下這個文件夾,直到找到指定的模板,因此如果不同應用下有同名的模板,Django很可能找錯。因此建議的做法是,在每個應用下的templates文件夾下創建以應用名命名的文件夾,將與該應用相關的模板放在這個文件夾中,就像這樣:app/templates/app/XXX.html。當視圖函數返回render響應時,相應地在模板名稱前加上app的名字,就像這樣:return render('app/XXX.html')
2 模板變量
2.1 深度查詢
Django的模板引擎能識別python中所有類型的變量,對于列表、字典、和對象這些復雜的變量,我們可以通過萬能的句點法(深度查詢)來訪問集合或對象,比如:
<p>對列表取值:{{ list.index }}</p> <P>對字典取值: {{ dict.key }}</P> <P>訪問對象的屬性: {{ obj.attr }}</P>2.2 使用變量過濾器
作用:修改變量在模板中的顯示
格式:{{ var|filter: arg }} 注意,過濾器函數默認接收變量,除此之外,最多只能接收一個參數
看個栗子:
1.我們在視圖函數中定義一些變量,通過locals()全部傳入模板渲染
2.在模板中應用過濾器來修改變量
<h1>filter過濾器效果!</h1> <h3>{{ string }} --> {{ string|cut:" " }} 剔除指定字符串</h3> <h3>{{ day }} --> {{ day|date:"Y-m-d" }} 格式化日期</h3> <h3>{{ l }} --> {{ l|default:"查詢結果為空" }} 當集合為空時,設置默認顯示,比如數據庫查詢結果為空時,我們自定義前端的提示信息</h3> <h3>{{ post }} --> {{ post|truncatewords:6 }} 截斷指定數量的單詞,可用于顯示文章摘要</h3> <h3>{{ k }} --> {{ k|join:", " }} 拼接列表</h3> <h3>{{ size }} --> {{ size|filesizeformat }} 顯示友好的文件大小</h3>3.瀏覽器顯示效果:
4.變量過濾器一覽
| add | 給變量加上一個值 |
| addslashes | 給變量中的引號前加/斜線 |
| capfirst | 首字母大寫 |
| lower | 轉換為小寫 |
| truncatewords:30 | 截斷指定數量的單詞,可用于顯示文章摘要 |
| join | 用指定字符拼接列表 |
| default | 如果變量為空或false,使用默認值 |
| length | 顯示字符串/列表的長度 |
| filesizeformat | 顯示易讀的文件大小 |
| date | 格式化日期字符串 |
| cut | 從字符串中移除指定的字符 |
| safe | 渲染值時不轉義。出于安全考慮,模板引擎會轉義所有的變量。如果確實需要顯示變量中的html代碼,就可以使用safe過濾器。不要對不可信的變量使用safe過濾器,比如用戶提交的表單中輸入的文本,可能包含攻擊代碼。 |
過濾器也支持鏈式操作:
{{ var|filter1|filter2 }}
5.更多過濾器的使用,請參考 built-in filter reference
2.3 自定義過濾器和標簽
2.3.1 自定義過濾器
過濾器本質就是一個函數,只需要如下幾步,我們也可以定制自己的過濾器
1. 將當前應用添加到settings.py的INSTALLED_APPS 列表中
2. 在項目的應用文件夾下新建一個包,命名為templatetags
3. 在剛剛新建的包下寫一個腳本,比如my_filter.py:
4. 在模板的<head>標簽內中導入自定義的過濾器(使用前導入就行,不一定非要在<head>內):{% load my_filter %} 。另外,發現一個問題,自定義過濾器導入后,自帶的過濾器可能工作不正常,具體原因不明,有知道的伙伴可以分享下。
5. 重啟服務,你就可以使用自定義的過濾器了
2.3.2 自定義標簽
自定義標簽的流程和自定義過濾器是相同的,只是裝飾器修改為@register.simple_tag
另外在使用格式上,自定義標簽是這樣:
{% func var [arg1] [arg2] ... [argn] %}
二者的其他差異:
1. 過濾器除了接收變量本身,最多可以額外接收一個參數,而自定義標簽無限制
2. 過濾器可以配合其它標簽使用,比如if控制語句:
補充:自定義標簽的另一種形式 inclusion_tag:
應用下新建templatetags目錄,新建腳本custom_tag.py,通過inclusion_tag自定義標簽
from django.template.library import Libraryregister = Library()@register.inclusion_tag('sample.html') def get_result(x):print('do something')return {'content': 'XXX', 'comments': ['aa', 'bb', 'cc']}說明:
- inclusion_tag接收一個模板路徑,這里是”sample.html”,并將函數的返回值拿到模板中渲染
- “sample.html”模板的渲染結果,返回給調用該自定義標簽的模板中,即步驟3的模板。
定義”sample.html”模板:
<div id="body">{{ content }} </div> <ul id="comment_list">{% for comment in comments %}<li>{{ comment }}</li>{% endfor %} </ul>調用自定義標簽:
{% load custom_tag %}<div id="article">{% get_result x %} </div>?
3 控制結構
Django的模板引擎提供了多種控制結構,用來改變模板的渲染流程。
3.1 if語句
{% if user %}Hello, {{ user }}! {% else %}Hello, {{ Stranger }}! {% endif %}3.2 for循環
渲染從數據庫取出的一組評論,使用for循環可以實現這一需求
<ul>{% for comment in comments %}<li>{{ comment }}</li>{% endfor %} </ul>3.2.1 forloop變量
forloop用在for循環內,配合if語句,可以用來控制循環:
1. forloop.counter 索引,從1開始,可用于顯示清單中條目的序號
2. forloop.counter0 索引,從0開始
3. forloop.revcounter 索引,倒序到1
4. forloop.revcounter0 索引,倒序到0
5. forloop.first 當第一次循環時,值為True
6. forloop.last 當第一次循環時,值為False
看個栗子:
<ul>{% for comment in comments %}<!-- 如果是第一條評論,就給它加某種樣式 -->{% if forloop.first %}<li class="first">{% else %}<li>{% endif %}{{ comment }}</li>{% endfor %} </ul>3.2.2 for … empty
for循環可以可以接受一個{% empty %}從句,如果循環的對象為空,將顯示{% empty %}從句下的內容:
<ul> {% for comment in comments %}<li>{{ comment }}</li> {% empty %}<li>No comments yet!</li> {% endfor %} </ul>3.3 代碼重用
3.3.1 模板繼承
模板繼承(extends)類似Python中的類繼承。它允許我們重用模板中相同的部分,定制不同的部分。首先,創建一個名為base.html的基模板:
<html> <head>{% block head %}<title>{% block title %}Title{% endblock %}</title>{% endblock %} </head> <body> {% block body %} {% endblock %} </body> </html>block標簽定義的塊可以在衍生模板中修改,并且每個block標簽都有名字。這里,我們只是簡單定義了head, title(因為每個頁面都應該顯示一個不同title), body的塊。注意,title包含中head中。下面我們來寫一個基模板的衍生模板:
{% extends 'base.html' %} {% block title %}Home{% endblock %} {% block head %}{{ block.super }}<style></style> {% endblock %} {% block body %} <h1>Hello, World!</h1> {% endblock %}}{% extends 'base.html' %}繼承指令放在首行,聲明該模板衍生自base.html。我們在衍生模板中重定義了三個block的內容,模板引擎會根據block名字,將其插入適當的位置。另外,通過{% block.super %},可以重用原來block中的內容,以便在其基礎上添加內容。
3.3.2 模板包含
需要在多處重復使用的模板代碼片段可以寫在單獨的文件,再包含(include)在要用的模板中,以避免重復:
{% include 'common.html' %}
3.4 其它標簽
- {% url %} 通過視圖函數別名,生成url絕對路徑,它還可以接收路由分組的參數: {% url 'name' v1 v2 %}
- {% with %} 用更簡單的變量名替代復雜的變量名
- {% verbatim %} 告訴模板引擎,不要渲染這個標簽內的內容
- {% load %} 載入自定義的模板標簽,記住,目標不加引號
更多標簽,請參考官網built-in-tag-reference
模板上下文處理器
令某些變量在所有模板中可用,比如,網站的頂部分類菜單,在很多頁面中都是相同的。
settings.py:
TEMPLATES = [{'BACKEND': 'django.template.backends.django.DjangoTemplates','DIRS': [os.path.join(BASE_DIR, 'templates')],'APP_DIRS': True,'OPTIONS': {'context_processors': ['django.template.context_processors.debug',# ...'app.views.get_funcs', # 視圖加入上下文處理器列表],},}, ] FUNCTIONS = [(1,"園子"),(2,"隨筆"),(3,"新聞"),(4,"博文"), ]views.py
def get_funcs(request):return ({"funcs": settings.FUNCTIONS})template: funcs變量在所有模板中可用
{% for func in funcs %}<li><a href="#">{{ func.1 }}</a></li> {% endfor %}總結
以上是生活随笔為你收集整理的Django(三)模板的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 网站安全狗V3.0—— .NET安全设置
- 下一篇: 进程间的通信