Django模板層
阿新 • • 發佈:2020-10-12
一 模板語法傳值
{{}}:變數相關
{%%}:邏輯相關
#從檢視函式的返回值中可以傳入任意型別的變數到trmplate的html的檔案中 #可以傳入函式與類 1. 傳入的函式會自動加括號呼叫 2. 在html檔案中不能傳入引數,不然不會被識別 3. 在瀏覽器中顯示的是函式的返回值 4. 展示到html頁面中也會觸發類的__str__方法類似於列印 5. 傳入類返回到html頁面中的是類中的物件,也是相當於直接加括號呼叫例項化一個物件 6. 取列表或是字典中的單個元素只能用.的方式調用出來 # .索引 也可以 .鍵 也能兩者混用 locals() 返回檢視函式中所有定義的變數到html檔案中 # 每一個web框架,都應該支援渲染模板 # 從檢視函式的返回值中傳入任意型別的變數到trmplate的html的檔案中,然後再html檔案中進行模板渲染的過程叫做DTL
過濾器
# 過濾器就類似於是模板語法內建的內建方法 # djangon內建有60多個過濾器,基本瞭解10個左右 # 基本語法 {{資料|過濾器:引數}} 變數名為 name 統計長度:{{ name |lenth }} 預設值:{{ name |default:'預設值' }} # name有值則列印這個值,沒有比如false返回預設值 file_size=123321 檔案大小: { { file_size | filesiezformat }} # 返回檔案大小自動補單位 日期格式化:{{current_time|date:'Y-m-d H:i:s'}} 切片操作: {{ name|slice:'2:4'}} 從索引2開始切到索引4 切取字元: { info |truncatechars:6} 包含三個點 #你好啊... 切取單詞: { info |truncatewords:9} 不包含三個(按照空格切,中文英文都是一樣) 移除特定字元:{{ info | cut:''}} 清除字串中的空格 拼接操作:{{list | join:'!'}} 列表拼接成字串 拼接操作:{{number | add:10}} 如果是數字,做數學運算 。如果是字串做拼接。如果都不是或一個數字一個 字串返回空 #重要 前端: hhh='<h1>阿里</h1>' 取消轉義:{ { hhh }} 標籤不可被識別 可以轉義:{{hhh|safe}} 標籤可被識別 後端: res = mark_safe('<h1>阿里</h1>') 轉義 ''' 說明以後全棧專案時,前端程式碼不一定非要在前端頁面書寫 也可以先在後端寫好,然後傳遞給前端頁面 如果沒有mark_safe保護則容易遭受xss攻擊 簡單介紹 就是輸入的字串可以轉義成相關程式碼執行 那麼在前端頁面的input欄中如果輸入惡意程式碼 後端拿到後是會儲存到資料庫中,且會被以程式碼的方式執行 那麼就會造成資料不安全的隱患 但是django內建的mark_safe就解決了這個問題 '''
標籤
# for 迴圈 {% for li in lis %} <p>{{ forloop }}</p> <p>{{ li }}</p> {% endfor %} # 列印了每次迴圈時當時變數的內建屬性 -1.counter0:從0開始,每迴圈一次加1 -2.counter: 從1開始,每迴圈一次加1 -3.revcounter:從整體的長度開始,每迴圈一次減1一直到1(倒數) -4.revcounter0:從最大的索引開始,每迴圈一次減1一直到0 -5.first:判斷是不是迴圈的第一個 -6.last: 判斷是不是迴圈的最後一個 -7.parentloop:父級forloop物件(for迴圈巢狀) {'parentloop': {}, 'counter0': 0, 'counter': 1, 'revcounter': 6, 'revcounter0': 5, 'first': True, 'last': False} {'parentloop': {}, 'counter0': 1, 'counter': 2, 'revcounter': 5, 'revcounter0': 4, 'first': False, 'last': False} {'parentloop': {}, 'counter0': 2, 'counter': 3, 'revcounter': 4, 'revcounter0': 3, 'first': False, 'last': False} {'parentloop': {}, 'counter0': 3, 'counter': 4, 'revcounter': 3, 'revcounter0': 2, 'first': False, 'last': False} {'parentloop': {}, 'counter0': 4, 'counter': 5, 'revcounter': 2, 'revcounter0': 1, 'first': False, 'last': False} {'parentloop': {}, 'counter0': 5, 'counter': 6, 'revcounter': 1, 'revcounter0': 0, 'first': False, 'last': True} # if 判斷 {% if flag %} <script> alert('重新輸入') </script> {% else %} <script> alert('登入成功') </script> {% endif %} # 兩者混用 {% for li in lis %} {% if forloop.first %} <p>這是我第一次</p> {% elif forloop.last %} <p>這是我最後一次</p> {% else %} <p>{{ li }}</p> {% endif %} {% empty %} <p> for迴圈的迭代物件為空 </p> #不代表迴圈物件迭代完就能觸發 {% endfor %} # 起別名 {% with dic.hobby.3 as name %} <p>{{name}}</p> {% enwith %} # csrf標籤(瞭解)
自定義標籤和過濾器
# 自定義標籤
-1.在setting中的INSTALLED_APPS配置當前app,不然Django無法找到自定義的simple_tag
-2.在app中建立templatetags包 # 注意:包名只能是templatetags,不能改
-3.在包內,新建py檔案 # 如:my_tags.py
-4.寫過濾器的邏輯程式碼
from django import template
register = template.Library()
@register.filter
def my_upper(values):
return values.upper()
-5.渲染模板,先load,再使用
<p>內建的過濾器:{{ 'abab'|upper }}</p>
{% load my_tag %}
<p>自定義的過濾器:{{ 'abab'|my_upper }}</p>
# 自定義標籤
-1.在setting中的INSTALLED_APPS配置當前app,不然Django無法找到自定義的simple_tag
-2.在app中建立templatetags包 # 注意:包名只能是templatetags,不能改
-3.在包內,新建py檔案 # 如:my_tags.py
-4.寫過濾器的邏輯程式碼
from django import template
from django.utils.html import mark_safe
register = template.Library()
@register.simple_tag
def my_csrf():
import uuid
res = uuid.uuid4()
return mark_safe('<input type="hidden" name="csrfmiddlewaretoken" value="%s">' % res)
-5.渲染模板,先load,在使用
{% csrf_token %}
{% my_csrf %}
'''
內建標籤在瀏覽器顯示:<input type="hidden" name="csrfmiddlewaretoken" value="ZefILcDWtxMlSb2mhS8bGbtscpnYRiJuctBGWRwGC7DMC0rZ3xLFwBznexljvKFI">
自定義標籤在瀏覽器顯示:<input type="hidden" name="csrfmiddlewaretoken" value="d39fd1ad-ba68-4123-af4b-82f5969bba1d">
'''
二 模板的繼承
'''
有些網站的頁面整體大差不差 風格形式相同 只是某一些區域性在變化
'''
# 模板的繼承 你自己先選好一個你想要繼承的模板頁面
{% entends 'home.html' %}
# 繼承了之後頁面跟模板頁面長得一模一樣,需要在模板頁面上劃定可以被修改的區域
{% block content %}
模板內容
{% endblock %}
# 子頁面就可以宣告想要修改的劃定了的區域
{% block content %}
子頁面內容
{% endblock %}
# 一般情況下模板頁面上應該至少有三塊可以被修改的區域
1.css區域
2.html區域
3.js區域
# 作用:每個子頁面都可以有自己獨有的css程式碼、html程式碼、js程式碼
'''
一般情況下 模板的頁面劃定的區域越多 擴充套件性越高
但是如果太多 不如自己寫
'''
三 模板的匯入
'''
將頁面的某一個區域性當成模組的形式
哪個地方需要就可以直接匯入即可
'''
-第一步:新建一個 xx.html,把好看的模板寫入
<div class="panel panel-danger">
<div class="panel-heading">
<h3 class="panel-title">重金求子</h3>
</div>
<div class="panel-body">
詳情點選:<a href="http://www.baidu.com">瘋狂點我</a>
</div>
</div>
-第二步:再你想用的地方
{% include 'xx.html' %}
四 前後端互動編碼方式
1.urlencoded----->傳普通的資料,form表單預設就是這種----->request.POST
2.form-data------>傳檔案和資料 ----->request.POST request.FILES
3.json----------->傳json格式資料 ------>request.body 反序列化處理
def index(request):
# 接收urlencoded編碼
body體中:name = lqz&age = 18
# print(request.POST) 最好通過此方式獲得資料
# 接收form-data編碼
body體中:分兩部分,一部分是資料,一部分是檔案
資料部分:name=lqz&age=18
-------------------------
檔案部分(二進位制)
# 資料部分
# print(request.POST)
# #檔案部分
# print(request.FILES)
# 接收json格式
body體中
{
"name": "lqz",
"age": 18
}
# 這裡沒有
print(request.POST)
# 資料在這(自行處理)
print(request.body)
return HttpResponse('ok')
五 靜態檔案相關
# 三種方式
# 如:在html檔案中匯入本地的bootstrap的樣式
第一種:
<link rel="stylesheet" href="/static/bootstrap/css/bootstrap.min.css">
第二種:
{% load static %}
<link rel="stylesheet" href="{% static 'bootstrap/css/bootstrap.min.css' %}">
相當於先找到了配置檔案setting.py 中的 STATIC_URL = '/static/'
那麼是動態的匯入模組,比如就算 STATIC_URL = '/aaaa/' 改成這樣子 也能成功匯入
第三種:
{% load static %}
<link rel="stylesheet" href="{% get_static_prefix %}bootstrap/css/bootstrap.min.css">
# 推薦使用第二種
# 特殊用法
# 如果匯入檔案的檔名過長,如圖片檔案,且之後要重複使用,那可以在第一次匯入時取別名
{% load static %}
<img src="{% static '1036857-20180821192355156-1472752634.png' as myphotor%}" alt="">
<img src="{{ myphotor }}" alt="">
<img src="{{ myphotor }}" alt="">
<img src="{{ myphotor }}" alt="">
<img src="{{ myphotor }}" alt="">
六 inclusion_tag的使用
# 可以生成一片模板中的程式碼塊
# 使用:6步
-第一步:在settings中的INSTALLED_APPS配置當前app,不然django無法找到自定義的simple_tag
-第二步:在app中建立templatetags包(包名只能是templatetags,不能改)
-第三步:在包內,新建py檔案(如:my_tags.py)
-第四步:寫程式碼(inclusion_tag)
@register.inclusion_tag('flag.html') # 在此html檔案中進行渲染
def flag(num):
dic = {i: '第%s頁' % i for i in range(num)}
# 固定返回的必須是字典
print(dic)
return {'dic': dic}
-第五步:在定義的第三方模板進行渲染
<ul>
{% for k,v in dic.items %}
<li>{{ v }}</li>
{% endfor %}
</ul>
-第六步:在需要返回到瀏覽器的模板中,動態的匯入已經在第三方渲染好的模板
{% load my_tag %}
{% flag 10 %} # 傳入引數匯入10個頁面
# 相比一般的include匯入模板,這樣的自定義可以傳參具有更高的延展性
# 它跟tag有什麼不同?
-tag需要再程式碼中寫html的東西
返回時需要mark_safe一個html檔案的內容,造成了程式碼的冗餘
-inclusion_tag程式碼跟模板分離
通過@register.inclusion_tag('flag.html')選擇一個第三方模板將資料在此模板渲染好了
再匯入需要此模板的html檔案中(解耦合)
七 練習
# 在請求頭中建立頭data 在其中可以取urlencoded,form-data,json這三種編碼格式的資料
# 寫一個裝飾器
def data(func):
def wrapper(request, *args, **kwargs):
import json
try:
# 如果能夠正常反序列化說明是Json格式,然後放入請求頭data中
# 如果不是則觸發異常捕獲
obj = json.loads(request.body)
request.data = obj
except Exception as e:
# 這時已經說明肯定是其他編碼格式(urlencoded,form-data)
obj = request.POST
# 直接新增
request.data = obj
res = func(request, *args, **kwargs) # request請求作為已知必須的傳入的引數可以單獨拿出來
return res
return wrapper
@data
def login(request):
if request.method == 'GET':
return render(request, 'login.html')
else:
name = request.data.get('name') # 可直接從請求頭data中取資料
pwd = request.data.get('password')
all_info = models.UserInfo.objects.all()
for user in all_info:
if name == user.name and pwd == user.password:
return HttpResponse('successful')
else:
return render(request, 'login.html', {'flag': True})
# 在響應體中新增請求頭
def home(request):
obj = render(request, 'home.html', {'flag': 'abab'})
obj['name'] = 'arther'
obj['age'] = 18
return obj
# 瀏覽器終端顯示
age: 18
Content-Length: 1392
Content-Type: text/html; charset=utf-8
Date: Mon, 12 Oct 2020 09:21:05 GMT
name: arther
Referrer-Policy: same-origin
Server: WSGIServer/0.2 CPython/3.8.4
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
# 遮蔽敏感詞彙
def work(request):
if request.method == 'GET':
# 通過GET請求的方式先返回一個輸入文字框的頁面
return render(request, 'work.html')
import re
name = request.POST.get('name')
obj = re.findall('.*?(草你媽|傻逼|狗子|你媽)', name)
# 正則中的分組每次只能返回一個匹配內容,通過.*?的方式匹配完字串所有的內容,匹配到一個內容後不會再重頭,而是繼續匹配分組內的其他字元,並以列表的方式儲存
# 通過正則匹配將輸入的內容中的敏感詞彙放入列表
if obj:
for i in obj:
if i in name:
# 得到敏感詞彙的長度
data = len(i)
name = name.replace(i, '*' * data)
return HttpResponse(name)