mycat設定讀寫分離
django模板
配置
在settings.py中配置,BACKEND
表示要使用那種模板引擎;DIRS
表示template的目錄(可以是多個);APP_DIRS
表示是否使用app中的template目錄(即形如這樣的app/templates/
);OPTIONS
是DjangoTemplates
的一些引數,預設即可。
比如:
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',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages' ,
],
},
},
]
要是想使用Jinja2:把BACKEND
改為django.template.backends.jinja2.Jinja2
即可。
當使用多個模板引擎時,django會按照列表的順序找到html檔案,然後渲染。需要注意的是:django查詢到任何一個匹配的模板後便停止搜尋,所以這是個類似url搜尋的短路操作!
使用
一般來說我們可以使用django.shortcuts.render
指定template檔案,然後進行渲染:
from django.shortcuts import render
def index (request):
return render(request, "app01/index.html")
render背後其實是這樣的:
from django.template import loader
from django.http import HttpResponse
def render(request, template_name, context=None, content_type=None, status=None, using=None):
content = loader.render_to_string(template_name, context, request, using=using)
return HttpResponse(content, content_type, status)
render的引數
- request是一個HttpRequest物件
- template_name:一般來說一個HTML檔案,其路徑需要在settings中配置好
- context:需要傳一個字典,裡面的鍵值對可以在html頁面中供模板引擎使用
- content_type:內容型別
模板語言
django作為一個重型web框架,自然少不了模板語言。這主要是用於動態渲染HTML頁面的。
變數
使用兩個大括號獲取,對於物件的屬性等資料可以在其基礎上是用.
獲取。對於Model物件,可以通過.
來取值,也可以使用.xxx_set
的方式進行反向查詢,但查詢操作不太適合在模板中完成。
比如:
# views.py
from django.shortcuts import render
def index(request):
data = {
"username": "lczmx",
"age": 22,
}
msg_list = ["1234", "abcd", "6666"]
print(request.session.get(""))
return render(request, "app01/index.html", {"data": data, "msg_list": msg_list})
<!-- app01/index.html -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>app01 index</title>
</head>
<body>
<p>{{ data.username }}</p>
<p>{{ data.age }}</p>
<p>{{ msg_list.0 }}</p>
</body>
</html>
標籤
django模板引擎的標籤就相當於python的程式碼塊,以{% %}
的定義。
django已經為我們貼心地內建了一下標籤 :
標籤 | 作用 |
---|---|
autoescape | 自動轉義開關 |
block | 塊引用 |
comment | 註釋 |
csrf_token | CSRF令牌 |
cycle | 迴圈物件的值 |
debug | 除錯模式 |
extends | 繼承模版 |
filter | 過濾功能 |
firstof | 輸出第一個不為False的引數 |
for | 迴圈物件 |
for … empty | 帶empty說明的迴圈 |
if | 條件判斷 |
ifchanged | 如果有變化,則.. |
include | 匯入子模版的內容 |
load | 載入標籤和過濾器 |
lorem | 生成無用的廢話 |
now | 當前時間 |
regroup | 根據物件重組集合 |
resetcycle | 重置迴圈 |
spaceless | 去除空白 |
templatetag | 轉義模版標籤符號 |
url | 獲取url字串 |
verbatim | 禁用模版引擎 |
widthratio | 寬度比例 |
with | 上下文變數管理器 |
對於使用方法,見:https://docs.djangoproject.com/zh-hans/3.2/ref/templates/builtins/
as語法的使用
使用as語法可以將返回值賦值給一個變數,如:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>app01 index</title>
</head>
<body>
{% url "app01:index" as index_url %}
<a href="{{ index_url }}">index page</a>
</body>
</html>
模板繼承:
extends與block結合,可以讓你的一些模板繼承其他模板,從而極大地減少程式碼的複用程度。
模板繼承允許你建立一個基本的“骨架”模板,它包含了你網站的所有常用元素,並定義了子模板可以覆蓋的 塊。
我們先看一個例子,看看模板繼承:
<!DOCTYPE html>
<html lang="en">
<head>
<link rel="stylesheet" href="style.css">
<title>{% block title %}My amazing site{% endblock %}</title>
</head>
<body>
<div id="sidebar">
{% block sidebar %}
<ul>
<li><a href="/">Home</a></li>
<li><a href="/blog/">Blog</a></li>
</ul>
{% endblock %}
</div>
<div id="content">
{% block content %}{% endblock %}
</div>
</body>
</html>
這個模板,我們稱之為base.html
,它定義了一個 HTML 骨架文件,你可以用它來製作一個兩欄式頁面。“子”模板的工作是用內容填充空塊。
在這個例子中,block 標籤定義了三個塊,子模板可以填入其中。block 標籤所做的就是告訴模板引擎,子模板可以覆蓋模板的這些部分。
一個子模板可能是這樣的:
{% extends "base.html" %}{% block title %}My amazing blog{% endblock %}{% block content %}{% for entry in blog_entries %}
<h2>{{ entry.title }}</h2>
<p>{{ entry.body }}</p>
{% endfor %}{% endblock %}
extends 標籤是這裡的關鍵。它告訴模板引擎,這個模板“擴充套件”了另一個模板。當模板系統執行這個模板時,首先要找到父模板——在本例中是“base.html”。
這時,模板引擎會注意到 base.html 中的三個 block 標籤,然後用子模板的內容替換這些塊。根據 blog_entries 的值,輸出可能是這樣的:
<!DOCTYPE html>
<html lang="en">
<head>
<link rel="stylesheet" href="style.css">
<title>My amazing blog</title>
</head>
<body>
<div id="sidebar">
<ul>
<li><a href="/">Home</a></li>
<li><a href="/blog/">Blog</a></li>
</ul>
</div>
<div id="content">
<h2>Entry one</h2>
<p>This is my first entry.</p>
<h2>Entry two</h2>
<p>This is my second entry.</p>
</div>
</body>
</html>
請注意,由於子模板沒有定義 sidebar
塊,所以使用父模板的值來代替。父模板中 {% block %} 標籤中的內容總是被用作後備。
你可以根據需要使用任意層次的繼承。一種常見的使用繼承的方式是像以下的三層繼承:
- 建立一個 base.html 模板,以保持你網站的主要外觀和風格。
- 為你網站的每個“部分”建立一個 base_SECTIONNAME.html 模板。
例如,base_news.html、base_sports.html。這些模板都是對 base.html 的擴充套件,幷包括特定部分的樣式/設計。 - 為每種型別的頁面建立單獨的模板
如新聞文章或部落格條目。這些模板擴充套件了相應的部分模板。
下面是一些關於繼承工作的技巧:
- 如果你在模板中使用 {% extends %},它必須是該模板中的第一個模板標籤。否則,模板繼承將無法使用。
- 基礎模板中的 {% block %} 標籤越多越好。記住,子模板不需要定義所有的父塊,所以你可以在一些塊中填入合理的預設值,然後只定義以後需要的塊。鉤子多比鉤子少好。
- 如果你發現自己的內容在多個模板中重複,可能意味著你應該把這些內容移到父模板中的 {% block %}。
- 如果你需要從父模板中獲取塊的內容,{{ block.super }} 變數就可以做到這一點。如果你想新增到父模板的內容中,而不是完全覆蓋它,這很有用。使用 {{ block.super }} 插入的資料不會被自動轉義,因為如果需要的話,它已經在父模板中被轉義了。
- 通過使用與繼承模板相同的模板名稱,{% extends %} 可以在覆蓋模板的同時繼承它。結合 {{ block.super }},這可以成為一種強大的小規模定製方式。 比如官方給出的這個例子:擴充套件複寫模板。
在 {% block %}
之外使用模板標籤 as
語法建立的變數不能在塊中使用。例如,這個模板不會呈現任何東西:
{% translate "Title" as title %}{% block content %}{{ title }}{% endblock %}
為了增加可讀性,你可以給你的 {% endblock %}
標籤 起一個 名字。例如:
{% block content %}
...
{% endblock content %
}
在較大的模板中,這種技術可以幫助你看到哪些{% block %}
標籤正在被關閉。
最後,請注意,你不能在同一個模板中定義多個同名的 block 標籤。
過濾器
過濾器就相當於python語法中的函式,其使用語法是:{{ 變數 | 過濾器:引數 }}
,其中,對於沒有引數的過濾器來說,:引數
這部分省略。
內建過濾器
過濾器 | 說明 |
---|---|
add | 加法 |
addslashes | 新增斜槓 |
capfirst | 首字母大寫 |
center | 文字居中 |
cut | 切除字元 |
date | 日期格式化 |
default | 設定預設值 |
default_if_none | 為None設定預設值 |
dictsort | 字典排序 |
dictsortreversed | 字典反向排序 |
divisibleby | 整除判斷 |
escape | 轉義 |
escapejs | 轉義js程式碼 |
filesizeformat | 檔案尺寸人性化顯示 |
first | 第一個元素 |
floatformat | 浮點數格式化 |
force_escape | 強制立刻轉義 |
get_digit | 獲取數字 |
iriencode | 轉換IRI |
join | 字元列表連結 |
json_script | 生成script標籤,帶json資料 |
last | 最後一個 |
length | 長度 |
length_is | 長度等於 |
linebreaks | 行轉換 |
linebreaksbr | 行轉換 |
linenumbers | 行號 |
ljust | 左對齊 |
lower | 小寫 |
make_list | 分割成字元列表 |
phone2numeric | 電話號碼 |
pluralize | 複數形式 |
pprint | 除錯 |
random | 隨機獲取 |
rjust | 右對齊 |
safe | 安全確認 |
safeseq | 列表安全確認 |
slice | 切片 |
slugify | 轉換成ASCII |
stringformat | 字串格式化 |
striptags | 去除HTML中的標籤 |
time | 時間格式化 |
timesince | 從何時開始 |
timeuntil | 到何時多久 |
title | 所有單詞首字母大寫 |
truncatechars | 截斷字元 |
truncatechars_html | 截斷字元 |
truncatewords | 截斷單詞 |
truncatewords_html | 截斷單詞 |
unordered_list | 無序列表 |
upper | 大寫 |
urlencode | 轉義url |
urlize | url轉成可點選的連結 |
urlizetrunc | urlize的截斷方式 |
wordcount | 單詞計數 |
wordwrap | 單詞包裹 |
yesno | 將True,False和None,對映成字串‘yes’,‘no’,‘maybe’ |
一般的使用例子,以add為例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>app01 index</title>
</head>
<body>
<p>你明年的年齡是{{ data.age | add:1 }}</p>
</body>
</html>
其他的內建過濾的參考。
關於safe字串,見:幾種safe字串的方法
自定義標籤及過濾器
一般來說,預設的標籤和過濾器已經夠我們應付簡單場景的了,面對複雜的需求的話,我們可以使用自定義標籤和過濾器的辦法。
自定義標籤及過濾器的位置就是 Django 應用內。如果它們關聯至某個已存在的應用,在那裡將它們打包就很有用;否則,它們能被新增至新應用。當一個 Django 應用被新增至 INSTALLED_APPS,所以其在常規位置定義的標籤都可以在模板中自動載入。
自定義標籤
- app中建立一個名為templatetags的Python 包
- 在templatetags下建立一個py檔案,用於放標籤函式
- 建立一個函式
- 使用
django.template.Library
物件的simple_tag
方法裝飾,可以指定name引數,表示標籤名,空的時候為函式名 - 重啟django
- 在template中使用load標籤將自定義標籤引入
- 以
{% xx %}
的形式使用
例子:
# 第1和第2步省略
# app的目錄機構(部分):
# app01
# ├── admin.py
# ├── apps.py
# ├── templatetags
# │ ├── __init__.py
# │ ├── mytags.py
# │ └── __pycache__
# │ ├── __init__.cpython-38.pyc
# │ └── mytags.cpython-38.pyc
# ├── tests.py
# ├── urls.py
# └── views.py
# app01/templatetags/mytags.py
from django import template
# 第4步
register = template.Library()
# 指定name引數為t1,在template中就只能用t1了
@register.simple_tag(name="t1")
def my_tag(x, y, *args):
print(x, y)
print(args)
return "t1"
{# 使用load自定義標籤,mytags是py檔案,t1是name指定的引數, 若不指定,則為函式名#}{% load t1 from mytags %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>app01 index</title>
</head>
<body>
{# 使用t1標籤 #}{% t1 12 234 134 %}
</body>
</html>
自定義過濾器
- app中建立一個名為templatetags的Python 包
- 在templatetags下建立一個py檔案,用於放過濾器函式
- 建立一個函式
- 使用
django.template.Library
物件的filter
方法裝飾,可以指定name引數,表示過濾器名,空的時候為函式名 - 重啟django
- 在template中使用load標籤將自定義過濾器引入
- 以
{{ xx | yy:z}}
的形式使用
filter和tag很像,就裝飾器、函式引數、模板使用方法有所區別,例子:
# app01/templatetags/myfilter.py
from django import template
register = template.Library()
@register.filter(name="f1")
def my_filter(x, y, z):
print(x, y, z)
return "f1"
{# 使用load自定義過濾器,myfilter是py檔案 #}{% load f1 from myfilter %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>app01 index</title>
</head>
<body>
{# 使用f1過濾器 #}{{ "hello"|f1:123 }}
</body>
</html>
load標籤的使用
load是用於載入一個自定義模板標籤集。
上面在例子使用了load標籤,下面記錄一下其語法。
在使用時可以把load類比成python的import
比如現在在templatetags下有兩個檔案,每個檔案中有一個標籤或過濾器函式:
# app/templatetags/myfilter.py
from django import template
register = template.Library()
@register.filter(name="f1")
def my_filter(x, y):
print(x, y)
return "f1"
# ########################################################## #
# app/templatetags/myfilter.py
from django import template
register = template.Library()
@register.simple_tag(name="t1")
def my_tag(x, y, *args):
print(x, y)
print(args)
return "t1"
那麼就有兩種方法載入:
第一種
{# load的是py檔案#}{% load mytags %}{% load myfilter %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>app01 index</title>
</head>
<body>
{# 直接使用 #}{% t1 12 234 134 %}{{ "hello"|f1:123 }}
</body>
</html>
方法二:
此方法可以同時載入多個,以空格隔開,如:{% load f1 f2 from myfliter %}
{#{% load t1 from mytags %}#}{#{% load f1 from myfilter %}#}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>app01 index</title>
</head>
<body>
{# 使用 #}{% t1 12 234 134 %}{{ "hello"|f1:123 }}
</body>
</html>