Django_render
模板語法
模板引擎是一種可以讓開發者把服務端資料填充到html網頁中完成渲染效果的技術,它實作了把前端代碼和服務端代碼分離的作用,讓專案中的業務邏輯代碼和資料表現代碼分離,讓前端開發者和服務端開發者可以更好的完成協同開發,
靜態網頁:頁面上的資料都是寫死的,萬年不變
動態網頁:頁面上的資料是從后端動態獲取的(比如后端獲取當前時間;后端獲取資料庫資料然后傳遞給前端頁面)
Django框架中內置了web開發領域非常出名的一個DjangoTemplate模板引擎(DTL),DTL官方檔案
要在django框架中使用模板引擎把視圖中的資料更好的展示給客戶端,需要完成3個步驟:
在專案組態檔中指定保存模板檔案的模板目錄,一般模板目錄都是設定在專案根目錄或者主應用目錄下,
在視圖中基于django提供的渲染函式系結模板檔案和需要展示的資料變數
在模板目錄下創建對應的模板檔案,并根據模板引擎內置的模板語法,填寫輸出視圖傳遞過來的資料,
配置模板目錄:在當前專案根目錄下創建了模板目錄templates. 然后在settings.py, 模板相關配置,找到TEMPLATES配置項,填寫DIRS設定模板目錄,
render內部本質

def index(request):
name = "hello world!"
# 1. 初始化模板,讀取模板內容,實體化模板物件
# get_template會從專案配置中找到模板目錄,我們需要填寫的引數就是補全模板檔案的路徑
template = get_template("index.html")
# 2. 識別context內容, 和模板內容里面的標記[標簽]替換,針對復雜的內容,進行正則的替換
context = {"name": name}
content = template.render(context, request) # render中完成了變數替換成變數值的程序,這個程序使用了正則,
print(content)
# 3. 通過response回應物件,把替換了資料的模板內容回傳給客戶端
return HttpResponse(content)
# 上面代碼的簡寫,直接使用 django.shortcuts.render
# return render(request, "index.html",context={"name":name})
# return render(request,"index3.html", locals())
# data = https://www.cnblogs.com/ivanlee717/p/{}
# data["name"] = "xiaoming"
# data["message"] = "你好!"
# return render(request,"index3.html", data)
- DTL模板檔案與普通html檔案的區別在哪里?
DTL模板檔案是一種帶有特殊語法的HTML檔案,這個HTML檔案可以被Django編譯,可以傳遞引數進去,實作資料動態化,在編譯完成后,生成一個普通的HTML檔案,然后發送給客戶端,
- 開發中,我們一般把開發中的檔案分2種,分別是靜態檔案和動態檔案,
- 靜態檔案,資料保存在當前檔案,不需要經過任何處理就可以展示出去,普通html檔案,圖片,視頻,音頻等這一類檔案叫靜態檔案,
- 動態檔案,資料并不在當前檔案,而是要經過服務端或其他程式進行編譯轉換才可以展示出去, 編譯轉換的程序往往就是使用正則或其他技術把檔案內部具有特殊格式的變數轉換成真實資料, 動態檔案,一般資料會保存在第三方存盤設備,如資料庫中,django的模板檔案,就屬于動態檔案,
模板語法內容
變數渲染(深度查詢、過濾器)
{{val}} {{val|filter_name:引數}}標簽
{% tag_name %}嵌套和繼承
1.1 深度查詢
def index(request):
name = "ZhangJR"
age = 22
is_married = True
course = ["global education","hongkong economy"]
regina = {
"name":"ZhangJR",
"age": 22,
"is_married": True,
}
class info():
def __init__(self,name,age):
self.name = name
self.age = age
Info = info("ZhangJR",22)
Info1 = info("ZhangJR",22)
Info2 = info("regina", 23)
Info3 = info("ivnalee", 24)
Info4 = info("qianniu", 25)
Infos = [Info1,Info2,Info3,Info4]
return render(request,"index.html",locals())
深度查詢在查詢屬性或者取值的程序都用
.作為判斷,locals函式代表將視圖函式所有的內容全部傳送給模板檔案渲染分別通過普通型別,字典型別,類,類的串列進行學習
<h3>深度查詢:句點符"."</h3>
<hr>普通型別
<p>姓名:{{name}}</p>
<p>年齡:{{age}}</p>
<p>婚否:{{is_married}}</p>
<p>課程:{{course}}</p>
<p>第一個課程:{{course.0}}</p>
<hr>字典
<p>個人資訊:{{regina}}</p>
<p>個人名字:{{regina.name}}</p>
<p>個人年齡:{{regina.age}}</p>
<hr>類物件
<p>類物件名字:{{Info.name}}</p>
<p>類物件年齡:{{Info.age}}</p>
<hr>類串列取值
<p>第二個人的姓名:{{Infos.1.name}}</p>

1.2 內置過濾器
語法:
{{obj|過濾器名稱:過濾器引數}}
內置過濾器
| 過濾器 | 用法 | 代碼 |
|---|---|---|
| last | 獲取串列/元組的最后一個成員 | {{list | last}} |
| first | 獲取串列/元組的第一個成員 | {{list|first}} |
| length | 獲取資料的長度 | {{list | length}} |
| default | 當變數沒有值的情況下, 系統輸出默認值, | {{str|default:"默認值"}} |
| safe | 讓系統不要對內容中的html代碼進行物體轉義 | {{htmlcontent| safe}} |
| upper | 字母轉換成大寫 | {{str | upper}} |
| lower | 字母轉換成小寫 | {{str | lower}} |
| title | 每個單詞首字母轉換成大寫 | {{str | title}} |
| date | 日期時間格式轉換 | `{{ value |
| cut | 從內容中截取掉同樣字符的內容 | {{content | cut:"hello"}} |
| list | 把內容轉換成串列格式 | {{content | list}} |
| add | 加法 | {{num| add}} |
| filesizeformat | 把檔案大小的數值轉換成單位表示 | {{filesize | filesizeformat}} |
join |
按指定字符拼接內容 | {{list| join("-")}} |
random |
隨機提取某個成員 | {list | random}} |
slice |
按切片提取成員 | {{list | slice:":-2"}} |
truncatechars |
按字符長度截取內容 | {{content | truncatechars:30}} |
truncatewords |
按單詞長度截取內容 | 同上 |
Infos = [Info1.name,Info2.name,Info3.name,Info4.name]
<p>資訊的最后一個人的姓名:{{Infos | last}}</p>
<p>資訊的第一個人的姓名:{{Infos | first}}</p>
<p>共有{{Infos | length}}個人</p>

-
默認值
如果渲染的值為空,可以添加默認渲染值,效果如圖
Name= "" 姓名{{Name}}
如果變成<p>姓名 {{Name|default:"regina"}}</p>(default后面不能有空格)

-
日期轉換
now = datetime.datetime.now() <p>當前時間默認格式:{{now}}</p> <p>格式化日期:{{now|date:"Y-m-d"}}</p> <p>格式化日期2:{{now|date:"D/d/m/Y"}}</p>
-
檔案大小
filesizeformat過濾器自動會識別位元組大小進行單位的選擇file1 = 717 file2 = 127717 file3 = 1271221 file4 = 1155178797 <p>檔案大小:{{file1|filesizeformat}}</p> <p>檔案大小:{{file2|filesizeformat}}</p> <p>檔案大小:{{file3|filesizeformat}}</p> <p>檔案大小:{{file4|filesizeformat}}</p>
-
按字符截斷
str = "ABCDEFGHIJK" <p>content: {{str | truncatechars:6}}</p>
這個...默認算作了一個字符
-
safe過濾
如果我們輸入的是一段帶有標簽的html語言,類似于
link = "<a href='https://www.cnblogs.com/ivanlee717/p/www.gs.cuhk.edu.hk'>cuhk</a>" script = "<script>alert('regina')</script>"如果正常傳輸,那網頁上得到的則是

并不是一個我們想要的效果,因為默認過濾器會對一些字符進行轉義,打開頁面原始碼就會發現這一問題

如果我們加上safe過濾器
<p>link:{{link| safe}}</p> <p>script:{{script|safe}}</p>


代碼也沒有進行任何的修改
1.3 自定義過濾器
雖然官方已經提供了許多內置的過濾器給開發者,但是很明顯,還是會有存在不足的時候,例如:希望輸出用戶的手機號碼時, 13912345678 ---->> 139*****678,這時我們就需要自定義過濾器,要宣告自定義過濾器并且能在模板中正常使用,需要完成2個前置的作業:
當前使用和宣告過濾器的子應用必須在setting.py組態檔中的INSTALLED_APPS中注冊了!!!
INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', ]這里面并沒有添加自定義的app進去,現在我們找到如下檔案,并在上述代碼添加
regina.apps.ReginaConfig
自定義過濾器函式必須被 template.register進行裝飾使用,而且過濾器函式所在的模塊必須在templatetags包里面保存
在home子應用下創建templatetags包[必須包含
__init__.py], 在包目錄下創建任意py檔案
myfilters的名字是自定義的,這里就是存盤過濾函式,并需要在最開始加上一些頭檔案
from django import template register = template.Library() @register.filter("mobile") def mobile(number): return number[:3]+"****"+number[-3:]在需要使用的模板檔案中頂部使用load標簽加載過濾器檔案my_filters.py并呼叫自定義過濾器
{% load myfilters %}過濾的函式要和myfilters檔案里面的函式是同名的
最終當輸入一個手機號時,得到就是一個隱藏后的手機號
2.1 標簽
{% tagname %}
if標簽
is_married = True
{% if is_married == True %}
<p>張女士已婚</p>
{% else %}
<p>張女士未婚</p>
{% endif %}
這里需要注意的幾個點:
- {% if condition %}這里的condition和if都需要和周圍的%空開一格
- {% if is_married == true %}這里要用雙等號
- 最后一定要加{% endif %}

<div>
{% if age < 20 %}
<p>太小</p>
{% elif age < 22 %}
<p>還行</p>
{% else %}
<p>正好</p>
{% endif %}
</div>
for回圈
<ul>
{% for name in course %}
<li>{{ name }}</li>
{% endfor %}
</ul>

<table border="1" align="center">
<tr>
<th>序號</th>
<th>姓名</th>
<th>年齡</th>
</tr>
{% for info in Infos %}
<tr align="center">
<td>{{ forloop.counter }}</td>
<td>{{ info.name }}</td>
<td>{{ info.age }}</td>
</tr>
{% endfor %}
</table>

還可以結合if判斷
{% for info in Infos %}
{% if forloop.first %}
<tr align="center" >
<td>{{ forloop.counter }}</td>
<td>{{ info.name }}</td>
<td>{{ info.age }}</td>
</tr>
{% else %}
<tr align="center">
<td>{{ forloop.counter }}</td>
<td>{{ info.name }}</td>
<td>{{ info.age }}</td>
</tr>
{% endif %}
{% endfor %}

或者還可以
{% elif info.age > 23 %}
<tr align="center" >
<td>{{ forloop.counter }}</td>
<td >{{ info.name }}</td>
<td>{{ info.age }}</td>
</tr>

回圈中, 模板引擎提供的forloop物件,用于給開發者獲取回圈次數或者判斷回圈程序的.
| 屬性 | 描述 |
|---|---|
| forloop.counter | 顯示回圈的次數,從1開始 |
| forloop.counter0 | 顯示回圈的次數,從0開始 |
| forloop.revcounter0 | 倒數顯示回圈的次數,從0開始 |
| forloop.revcounter | 倒數顯示回圈的次數,從1開始 |
| forloop.first | 判斷如果本次是回圈的第一次,則結果為True |
| forloop.last | 判斷如果本次是回圈的最后一次,則結果為True |
| forloop.parentloop | 在嵌套回圈中,指向當前回圈的上級回圈 |
3 嵌套繼承
傳統的模板分離技術,依靠{% include "模板檔案名"%}實作,這種方式,雖然達到了頁面代碼復用的效果,但是由此也會帶來大量的碎片化模板,導致維護模板的成本上升.因此, Django框架中除了提供這種模板分離技術以外,還并行的提供了 模板繼承給開發者.
{% include "模板檔案名"%} # 模板嵌入
{% extends "base.html" %} # 模板繼承
3.1 include
假設現在有兩個頁面公用一個同樣式的東西,即頁面底部有一個廣告~

在每一個頁面里都添加一句
{% include "same.html" %}


此時兩個頁面就同時擁有了這一元素
3.2 extends繼承
因為一個頁面繼承的東西可能有很多,而且有很多的固定框架,不可能每一個都用include進行繼承,此時就需要extends關鍵字,首先我們來用bootstrap學習一下,然后在我們需要自己渲染的位置上添加區塊
<div >
<div role="main">
{% block content %}
<p>hello world!</p>
{% endblock %}
</div>
</div>
其中content是自定義的名字,在模板檔案里也同樣要用這個名字,然后在其他檔案里進行匯入這個檔案
{% extends "same.html" %}
.....
{% block content %}
原來渲染的內容
{% endblock %}
被extends的檔案在未使用時是這樣的

我們看到有兩個塊是要傳遞給模板檔案渲染的,index.html和test.html同時繼承了這一檔案,效果如圖


- 如果你在模版中使用
{% extends %}標簽,它必須是模版中的第一個標簽,其他的任何情況下,模版繼承都將無法作業,- 在base模版中設定越多的
{% block %}標簽越好,請記住,子模版不必定義全部父模版中的blocks,所以,你可以在大多數blocks中填充合理的默認內容,然后,只定義你需要的那一個,多一點鉤子總比少一點好,- 為了更好的可讀性,你也可以給你的
{% endblock %}標簽一個 名字 ,例如:{``%block content``%``}``...``{``%endblock content``%``},在大型模版中,這個方法幫你清楚的看到哪一個{% block %}標簽被關閉了,- 不能在一個模版中定義多個相同名字的
block標簽,
在最開始的same頁面中,我們是添加了一句話的,雖然這句話并不重要,但是如果我們繼承的時候也想要這句話,就需要把陳述句改為
{% block content %}
{{ block.super }}
....

此時原來same.html里面的block內容也可以得到繼承
本文來自博客園,作者:ivanlee717,轉載請注明原文鏈接:https://www.cnblogs.com/ivanlee717/p/16695109.html
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/508061.html
標籤:Python
上一篇:python基礎(待補充)



