編程網(wǎng)課哪家好seo門戶
一 模版的使用
模板引擎是一種可以讓開發(fā)者把服務(wù)端數(shù)據(jù)填充到html網(wǎng)頁中完成渲染效果的技術(shù)。它實現(xiàn)了?把前端代碼和服務(wù)端代碼分離?的作用,讓項目中的業(yè)務(wù)邏輯代碼和數(shù)據(jù)表現(xiàn)代碼分離,讓前端開發(fā)者和服務(wù)端開發(fā)者可以更好的完成協(xié)同開發(fā)。
- 靜態(tài)網(wǎng)頁:頁面上的數(shù)據(jù)都是寫死的,萬年不變。
- 動態(tài)網(wǎng)頁:頁面上的數(shù)據(jù)是從后端動態(tài)獲取的(比如后端獲取當(dāng)前時間;后端獲取數(shù)據(jù)庫數(shù)據(jù)然后傳遞給前端頁面)。
要在django框架中使用模板引擎把視圖中的數(shù)據(jù)更好的展示給客戶端,需要完成3個步驟:
-
在項目配置文件中指定保存模板文件的模板目錄。一般模板目錄都是設(shè)置在項目根目錄或者主應(yīng)用目錄下。
-
在視圖中基于django提供的渲染函數(shù)綁定模板文件和需要展示的數(shù)據(jù)變量
-
在模板目錄下創(chuàng)建對應(yīng)的模板文件,并根據(jù)模板引擎內(nèi)置的模板語法,填寫輸出視圖傳遞過來的數(shù)據(jù)。
配置模板目錄:在當(dāng)前項目根目錄下創(chuàng)建了模板目錄templates. 然后在settings.py, 模板相關(guān)配置,找到TEMPLATES配置項,填寫DIRS設(shè)置模板目錄。
'DIRS': [BASE_DIR / "templates"]
# 模板引擎配置
TEMPLATES = [{'BACKEND': 'django.template.backends.django.DjangoTemplates','DIRS': [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',],},},
]
1.1?Render函數(shù)內(nèi)部本質(zhì)
from django.shortcuts import render
from django.template.loader import get_template
from django.http.response import HttpResponse
def index(request):name = "hello world!"# 1. 初始化模板,讀取模板內(nèi)容,實例化模板對象# get_template會從項目配置中找到模板目錄,我們需要填寫的參數(shù)就是補全模板文件的路徑template = get_template("index.html")# 2. 識別context內(nèi)容, 和模板內(nèi)容里面的標(biāo)記[標(biāo)簽]替換,針對復(fù)雜的內(nèi)容,進行正則的替換context = {"name": name}content = template.render(context, request) # render中完成了變量替換成變量值的過程,這個過程使用了正則。print(content)# 3. 通過response響應(yīng)對象,把替換了數(shù)據(jù)的模板內(nèi)容返回給客戶端return HttpResponse(content)# 上面代碼的簡寫,直接使用 django.shortcuts.render# return render(request, "index.html",context={"name":name})# return render(request,"index3.html", locals())# data = {}# data["name"] = "xiaoming"# data["message"] = "你好!"# return render(request,"index3.html", data)
DTL模板文件與普通html文件的區(qū)別在哪里?
DTL模板文件是一種帶有特殊語法的HTML文件,這個HTML文件可以被Django編譯,可以傳遞參數(shù)進去,實現(xiàn)數(shù)據(jù)動態(tài)化。在編譯完成后,生成一個普通的HTML文件,然后發(fā)送給客戶端。
開發(fā)中,我們一般把開發(fā)中的文件分2種,分別是靜態(tài)文件和動態(tài)文件。
- 靜態(tài)文件,數(shù)據(jù)保存在當(dāng)前文件,不需要經(jīng)過任何處理就可以展示出去。普通html文件,圖片,視頻,音頻等這一類文件叫靜態(tài)文件。
- 動態(tài)文件,數(shù)據(jù)并不在當(dāng)前文件,而是要經(jīng)過服務(wù)端或其他程序進行編譯轉(zhuǎn)換才可以展示出去。 編譯轉(zhuǎn)換的過程往往就是使用正則或其他技術(shù)把文件內(nèi)部具有特殊格式的變量轉(zhuǎn)換成真實數(shù)據(jù)。 動態(tài)文件,一般數(shù)據(jù)會保存在第三方存儲設(shè)備,如數(shù)據(jù)庫中。django的模板文件,就屬于動態(tài)文件。
1.2?模板語法
1.2.1?變量渲染
深度查詢、過濾器:
{{val}} # 渲染數(shù)據(jù)
{{val|filter_name:參數(shù)}}
1.2.2?標(biāo)簽
{% tag_name %} # 渲染邏輯
1.2.3 嵌套和繼承
{% extends "base_generic.html" %}{% block title %}{{ section.title }}{% endblock %}{% block content %}
5
<h1>{{ section.title }}</h1>{% for story in story_list %}
<h2><a href="{{ story.get_absolute_url }}">{{ story.headline|upper }}</a>
</h2>
<p>{{ story.tease|truncatewords:"100" }}</p>
{% endfor %}
{% endblock %}
1.2.4?變量渲染之深度查詢
class Book(object):def __init__():self.title=titleself.price=pricedef index(request):name = "root"age = 13sex = Truelve = ["swimming", "shopping", "coding", "game"]bookinfo = {"id": 1, "price": 9.90, "name": "python3天入門到掙扎", }book_list = [{"id": 10, "price": 9.90, "name": "python3天入門到掙扎", },{"id": 11, "price": 19.90, "name": "python7天入門到垂死掙扎", },]book01 = Book("三體",199)book02 = Book("體",99)book03 = Book("三",299)book04 = Book("票",39)books = [book01,book02,book03,book04] return render(request, 'index.html', locals())
模板代碼,templates/index.html:
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body><p>name={{ name }}</p><p>{{ age }}</p><p>{{ sex }}</p><p>列表成員</p><p>{{ lve }}</p><p>{{ lve.0 }}</p><p>{{ lve | last }}</p><p>字典成員</p><p>id={{ bookinfo.id }}</p><p>price={{ bookinfo.price }}</p><p>name={{ bookinfo.name }}</p><p>復(fù)雜列表</p><p>{{ book_list.0.name }}</p><p>{{ book_list.1.name }}</p><p>對象</p><p>{{ book01 }}</p><p>{{ book01.title }}</p><p>第三部書的價格{{ books.2.title }}</p></body>
</html>
<---通過句點符號深度查詢----!>
tem.urls?代碼:
"""子應(yīng)用路由"""
from django.urls import path, re_path
from . import viewsurlpatterns = [# ....path("index", views.index),
]
1.2.5?變量渲染之內(nèi)置過濾器
語法:
{{obj|過濾器名稱:過濾器參數(shù)}}
內(nèi)置過濾器:
過濾器的使用視圖代碼 home.views.py;
def index(request):"""過濾器 filters"""content = "<a href='http://www.luffycity.com'>路飛學(xué)城</a>"# content1 = '<script>alert(1);</script>'book2=[]from datetime import datetimenow = datetime.now()content2= "hello wrold!"#locals() 函數(shù)會以字典類型返回當(dāng)前位置的全部局部變量return render(request,"index.html",locals())
模板代碼,templates/index.html:
{{ content | safe }}{{ content1 | safe }}{# 過濾器本質(zhì)就是函數(shù),但是模板語法不支持小括號調(diào)用,所以需要使用:號分割參數(shù) #}<p>日期:{{ now | date:"Y-m-d H:i:s" }}</p>{# conten1如果是True正常顯示內(nèi)容 如果為False顯示default的默認(rèn)值 #}<p>book2展示:{{ conten1 | default:"暫時沒有符合條件的書籍" }}</p> {# 一個數(shù)據(jù)可以連續(xù)調(diào)用多個過濾器 #}<p>{{ content2 | truncatechars:6 | upper }}</p>{# safe 安全 django會把 <> 轉(zhuǎn)義成特殊符號 避免js腳本惡意攻擊 #}<p>鏈接:{{ content }}</p><p>鏈接:{{ content|safe }}</p> # 加上safe表明此鏈接安全 不會特殊處理{# 給書的價格加100 #}<p>鏈接:{{ book01.price|add:100 }}</p>
1.2.6?自定義過濾器
雖然官方已經(jīng)提供了許多內(nèi)置的過濾器給開發(fā)者,但是很明顯,還是會有存在不足的時候。例如:希望輸出用戶的手機號碼時, 13912345678 ----> 139*****678,這時我們就需要自定義過濾器。要聲明自定義過濾器并且能在模板中正常使用,需要完成2個前置的工作:
# 1. 當(dāng)前使用和聲明過濾器的子應(yīng)用必須在setting.py配置文件中的INSTALLED_APPS中注冊了!!!
INSTALLED_APPS = ['django.contrib.admin','django.contrib.auth','django.contrib.contenttypes','django.contrib.sessions','django.contrib.messages','django.contrib.staticfiles','home',
]
# --------------------------------------------------
# 2. 自定義過濾器函數(shù)必須被 template.register進行裝飾使用.
# 而且過濾器函數(shù)所在的模塊必須在templatetags包里面保存# 在home子應(yīng)用下創(chuàng)建templatetags包[必須包含__init__.py], 在包目錄下創(chuàng)建任意py文件
# home.templatetags.my_filters.py代碼:from django import template
register = template.Library()# 自定義過濾器
@register.filter("mobile")
def mobile(content):return content[:3]+"*****"+content[-3:]
# --------------------------------------------------
# 3. 在需要使用的模板文件中頂部使用load標(biāo)簽加載過濾器文件my_filters.py并調(diào)用自定義過濾器
# home.views.py,代碼:def index(request):"""自定義過濾器 filters"""moblie_number = "13312345678"return render(request,"index2.html",locals())
templates/index2.html?代碼:
# 將過濾器文件my_filters導(dǎo)入到模板里
{% load my_filters %}
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body>{{ moblie_number| mobile }}
</body>
</html>
1.2.7 if 標(biāo)簽
視圖代碼, tem.views.py:
def index(request):name = "xiaoming"age = 19sex = Truelve = ["swimming", "shopping", "coding", "game"]user_lve = "sleep"bookinfo = {"id": 1, "price": 9.90, "name": "python3天入門到掙扎", }book_list = [{"id": 10, "price": 9.90, "name": "python3天入門到掙扎", },{"id": 11, "price": 19.90, "name": "python7天入門到垂死掙扎", },]return render(request, 'index.html', locals())
?模板代碼, templates/index.html,代碼:
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body>
{# 來自django模板引擎的注釋~~~~ #}
{% comment %}
多行注釋,comment中的所有內(nèi)容全部都不會被顯示出去
{% endcomment %}# 條件成立會被渲染出來
{# {% if age < 18 %}#}
{# <p>你還沒成年,不能訪問我的網(wǎng)站!</p>#}
{# {% endif %}#}
{##}
{# {% if name == "root" %}#}
{# <p>超級用戶,歡迎回家!</p>#}
{# {% else %}#}
{# <p>{{ name }},你好,歡迎來到xx網(wǎng)站!</p>#}
{# {% endif %}#}{% if user_lve == lve.0 %}<p>那么巧,你喜歡游泳,海里也能見到你~</p>{% elif user_lve == lve.1 %}<p>那么巧,你也來收快遞呀?~</p>{% elif user_lve == lve.2 %}<p>那么巧,你也在老男孩?</p>{% else %}<p>看來我們沒有緣分~</p>{% endif %}
</body>
</html>
路由代碼:
"""子應(yīng)用路由"""
from django.urls import path, re_path
from . import viewsurlpatterns = [# ....path("index", views.index),
]
1.2.8 for 標(biāo)簽
視圖代碼, home.views.py:
def index7(request):book_list1 = [{"id": 11, "name": "python基礎(chǔ)入門", "price": 130.00},{"id": 17, "name": "Go基礎(chǔ)入門", "price": 230.00},{"id": 23, "name": "PHP基礎(chǔ)入門", "price": 330.00},{"id": 44, "name": "Java基礎(chǔ)入門", "price": 730.00},{"id": 51, "name": "C++基礎(chǔ)入門", "price": 300.00},{"id": 56, "name": "C#基礎(chǔ)入門", "price": 100.00},{"id": 57, "name": "前端基礎(chǔ)入門", "price": 380.00},]return render(request, 'index.html', locals())
template/index.html,代碼:
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body><table width="800" align="center" border="1"><tr><td>序號</td><td>id</td><td>標(biāo)題</td><td>價格</td></tr>
{# 多行編輯,alt+鼠標(biāo)鍵,alt不要松開,左鍵點擊要編輯的每一行 #}
{# {% for book in book_list1 %}#}
{# <tr>#}
{# <td>{{ book.id }}</td>#}
{# <td>{{ book.name }}</td>#}
{# <td>{{ book.price }}</td>#}
{# </tr>#}
{# {% endfor %}#}{# 建議不要直接使用for循環(huán)一維字典,此處使用僅僅展示for嵌套for而已 #}
{# {% for book in book_list1 %}#}
{# <tr>#}
{# {% for field,value in book.items %}#}
{# <td>{{ field }} == {{ value }}</td>#}
{# {% endfor %}#}
{# </tr>#}
{# {% endfor %}#}{# {% for book in book_list1 %}#}
{# <tr>#}
{# <td>{{ book.id }}</td>#}
{# <td>{{ book.name }}</td>#}
{# {% if book.price > 200 %}#}
{# <td bgcolor="#ff7f50">{{ book.price }}</td>#}
{# {% else %}#}
{# <td>{{ book.price }}</td>#}
{# {% endif %}#}
{# </tr>#}
{# {% endfor %}#}{# 逆向循環(huán)數(shù)據(jù) #}
{# {% for book in book_list1 reversed %}#}
{# <tr>#}
{# <td>{{ book.id }}</td>#}
{# <td>{{ book.name }}</td>#}
{# {% if book.price > 200 %}#}
{# <td bgcolor="#ff7f50">{{ book.price }}</td>#}
{# {% else %}#}
{# <td>{{ book.price }}</td>#}
{# {% endif %}#}
{# </tr>#}
{# {% endfor %}#}{% for book in book_list1 %}<tr>
{# <td>{{ forloop.counter }}</td>#} # forloop循環(huán)器 只能在for循環(huán)里使用 counter計數(shù)器
{# <td>{{ forloop.counter0 }}</td>#} # counter0 從0開始計數(shù)
{# <td>{{ forloop.revcounter }}</td>#}
{# <td>{{ forloop.revcounter0 }}</td>#}
{# <td>{{ forloop.first }}</td>#} # 是否是循環(huán)的第一個 返回布爾值<td>{{ forloop.last }}</td><td>{{ book.id }}</td><td>{{ book.name }}</td>{% if book.price > 200 %}<td bgcolor="#ff7f50">{{ book.price }}</td>{% else %}<td>{{ book.price }}</td>{% endif %}</tr>{% endfor %}</table>
</body>
</html>
路由代碼:
"""子應(yīng)用路由"""
from django.urls import path, re_path
from . import viewsurlpatterns = [# ....path("index", views.index),
]
循環(huán)中, 模板引擎提供的forloop對象,用于給開發(fā)者獲取循環(huán)次數(shù)或者判斷循環(huán)過程的.
1.2.9?模板嵌套繼承
傳統(tǒng)的模板分離技術(shù),依靠 {% include "模板文件名"%} 實現(xiàn),這種方式,雖然達到了頁面代碼復(fù)用的效果,但是由此也會帶來大量的碎片化模板(一直include),導(dǎo)致維護模板的成本上升.因此, Django框架中除了提供這種模板分離技術(shù)以外,還并行的提供了 模板繼承給開發(fā)者.
視圖, home.views.py代碼:
def index(request):"""模板繼承"""return render(request,"index.html",locals())
templates/index.html:
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body><h1>base.html的頭部</h1><h1>base.html的內(nèi)容</h1><h1>base.html的腳部</h1>
{% include "ad.html"%}
</body>
</html>
新建ad.html (不需要構(gòu)建新的頁面 只需要子頁面 提取出公共部分)
<style>.advertise{width:200pxheight:150px}
</style><div class='advertise'>廣告</div>
{% include "模板文件名"%} # 模板嵌入
{% extends "base.html" %} # 模板繼承
(1) 繼承父模板的公共內(nèi)容
{% extends "base.html" %}# 視圖, home.views.py代碼:def index(request):"""模板繼承"""return render(request,"index.html",locals())
子模板, templates/index.html{% extends "base.html" %}
父模板, templates/base.html<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body><h1>base.html的頭部</h1><h1>base.html的內(nèi)容</h1><h1>base.html的腳部</h1>
</body>
</html>
(2) 個性展示不同于父模板的內(nèi)容
{%block %} 獨立內(nèi)容 {%endblock%}{{block.super}}視圖home.views.py, 代碼:def index(request):"""模板繼承"""return render(request,"index.html",locals())def home(request):"""模板繼承"""return render(request,"home.html",locals())
路由 home.urls.py,代碼:from django.urls import path
from . import views
urlpatterns = [path("", views.index),path("home/", views.home),
]
子模板index.html,代碼:{% extends "base.html" %}
{% block title %}index3的標(biāo)題{% endblock %}
{% block content %}{{ block.super }} {# 父級模板同名block標(biāo)簽的內(nèi)容 #}<h1>index3.html的獨立內(nèi)容</h1>{{ block.super }}
{% endblock %}
子模板home.html,代碼:{% extends "base.html" %} # 繼承父模板
{% block title %}home的標(biāo)題{% endblock %} # 重寫父模板的盒子內(nèi)容
父模板base.html,代碼:<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>{% block title %}{% endblock %}</title>
</head>
<body><h1>base.html的頭部</h1>{% block content %}<h1>base.html的內(nèi)容</h1>{% endblock %}<h1>base.html的腳部</h1>
</body>
</html>
-
如果你在模版中使用 {% extends %} 標(biāo)簽,它必須是模版中的第一個標(biāo)簽。其他的任何情況下,模版繼承都將無法工作。
-
在base模版中設(shè)置越多的 {% block %} 盒子標(biāo)簽越好。請記住,子模版不必定義全部父模版中的blocks,所以,你可以在大多數(shù)blocks中填充合理的默認(rèn)內(nèi)容,然后,子模板只定義重寫你需要的那一個盒子,沒定義使用父模板的默認(rèn)內(nèi)容。多一點鉤子總比少一點好。
-
為了更好的可讀性,你也可以給你的 {% endblock %} 標(biāo)簽一個 名字 。例如:{
% block content
%}
...{
% endblock content%
},在大型模版中,這個方法幫你清楚的看到哪一個 {% block %} 標(biāo)簽被關(guān)閉了。 -
不能在一個模版中定義多個相同名字的 block 標(biāo)簽。
-
子模板里的{{ block.super }}? ?# 表示父模板的默認(rèn)內(nèi)容展示出來 不會被重寫內(nèi)容覆蓋
1.3?靜態(tài)文件
開發(fā)中在開啟了debug模式時,django可以通過配置,允許用戶通過對應(yīng)的url地址訪問django的靜態(tài)文件。
setting.py,代碼:# 可以訪問靜態(tài)資源的配置
STATIC_URL = '/static/'
STATICFILES_DIRS = [BASE_DIR / "static",
]
注意:項目上線以后,關(guān)閉debug模式時,django默認(rèn)是不提供靜態(tài)文件的訪問支持,項目部署的時候,我們會通過收集靜態(tài)文件使用nginx這種web服務(wù)器來提供靜態(tài)文件的訪問支持。