Django Views(视图函数)
http請求中產(chǎn)生兩個(gè)核心對象:
??????? http請求:HttpRequest對象
??????? http響應(yīng):HttpResponse對象
所在位置:django.http
之前我們用到的參數(shù)request就是HttpRequest ? ?檢測方法:isinstance(request,HttpRequest)
1 HttpRequest對象的屬性和方法:
# path: 請求頁面的全路徑,不包括域名 # # method: 請求中使用的HTTP方法的字符串表示。全大寫表示。例如 # # if req.method=="GET": # # do_something() # # elseif req.method=="POST": # # do_something_else() # # GET: 包含所有HTTP GET參數(shù)的類字典對象 # # POST: 包含所有HTTP POST參數(shù)的類字典對象 # # 服務(wù)器收到空的POST請求的情況也是可能發(fā)生的,也就是說,表單form通過 # HTTP POST方法提交請求,但是表單中可能沒有數(shù)據(jù),因此不能使用 # if req.POST來判斷是否使用了HTTP POST 方法;應(yīng)該使用 if req.method=="POST" # # # # COOKIES: 包含所有cookies的標(biāo)準(zhǔn)Python字典對象;keys和values都是字符串。 # # FILES: 包含所有上傳文件的類字典對象;FILES中的每一個(gè)Key都是<input type="file" name="" />標(biāo)簽中 name屬性的值,FILES中的每一個(gè)value同時(shí)也是一個(gè)標(biāo)準(zhǔn)的python字典對象,包含下面三個(gè)Keys: # # filename: 上傳文件名,用字符串表示 # content_type: 上傳文件的Content Type # content: 上傳文件的原始內(nèi)容 # # # user: 是一個(gè)django.contrib.auth.models.User對象,代表當(dāng)前登陸的用戶。如果訪問用戶當(dāng)前 # 沒有登陸,user將被初始化為django.contrib.auth.models.AnonymousUser的實(shí)例。你 # 可以通過user的is_authenticated()方法來辨別用戶是否登陸: # if req.user.is_authenticated();只有激活Django中的AuthenticationMiddleware # 時(shí)該屬性才可用 # # session: 唯一可讀寫的屬性,代表當(dāng)前會(huì)話的字典對象;自己有激活Django中的session支持時(shí)該屬性才可用。#方法 get_full_path(), 比如:http://127.0.0.1:8000/index33/?name=123 ,req.get_full_path()得到的結(jié)果就是/index33/?name=123 req.path:/index33?
注意一個(gè)常用方法:request.POST.getlist('')
2?HttpResponse對象:
? 對于HttpRequest對象來說,是由django自動(dòng)創(chuàng)建的,但是,HttpResponse對象就必須我們自己創(chuàng)建。每個(gè)view請求處理方法必須返回一個(gè)HttpResponse對象。
??HttpResponse類在django.http.HttpResponse
? 在HttpResponse對象上擴(kuò)展的常用方法:
頁面渲染: render()(推薦)<br> render_to_response(),頁面跳轉(zhuǎn): redirect("路徑")locals(): 可以直接將函數(shù)中所有的變量傳給模板?補(bǔ)充:
-----------------------------------url.pyurl(r"login", views.login),url(r"yuan_back", views.yuan_back),-----------------------------------views.py def login(req):if req.method=="POST":if 1:# return redirect("/yuan_back/")name="yuanhao"return render(req,"my backend.html",locals())return render(req,"login.html",locals())def yuan_back(req):name="苑昊"return render(req,"my backend.html",locals())-----------------------------------login.html<form action="/login/" method="post"><p>姓名<input type="text" name="username"></p><p>性別<input type="text" name="sex"></p><p>郵箱<input type="text" name="email"></p><p><input type="submit" value="submit"></p> </form> -----------------------------------my backend.html <h1>用戶{{ name }}你好</h1>#總結(jié): render和redirect的區(qū)別: # 1 if render的頁面需要模板語言渲染,需要的將數(shù)據(jù)庫的數(shù)據(jù)加載到html,那么所有的這一部分 # 除了寫在yuan_back的視圖函數(shù)中,必須還要寫在login中,代碼重復(fù),沒有解耦.# 2 the most important: url沒有跳轉(zhuǎn)到/yuan_back/,而是還在/login/,所以當(dāng)刷新后 # 又得重新登錄.七 Template基礎(chǔ)?
模板系統(tǒng)的介紹
你可能已經(jīng)注意到我們在例子視圖中返回文本的方式有點(diǎn)特別。 也就是說,HTML被直接硬編碼在 Python代碼之中。
def current_datetime(request):now = datetime.datetime.now()html = "<html><body>It is now %s.</body></html>" % nowreturn HttpResponse(html)盡管這種技術(shù)便于解釋視圖是如何工作的,但直接將HTML硬編碼到你的視圖里卻并不是一個(gè)好主意。 讓我們來看一下為什么:
-
對頁面設(shè)計(jì)進(jìn)行的任何改變都必須對 Python 代碼進(jìn)行相應(yīng)的修改。 站點(diǎn)設(shè)計(jì)的修改往往比底層 Python 代碼的修改要頻繁得多,因此如果可以在不進(jìn)行 Python 代碼修改的情況下變更設(shè)計(jì),那將會(huì)方便得多。
-
Python 代碼編寫和 HTML 設(shè)計(jì)是兩項(xiàng)不同的工作,大多數(shù)專業(yè)的網(wǎng)站開發(fā)環(huán)境都將他們分配給不同的人員(甚至不同部門)來完成。 設(shè)計(jì)者和HTML/CSS的編碼人員不應(yīng)該被要求去編輯Python的代碼來完成他們的工作。
-
程序員編寫 Python代碼和設(shè)計(jì)人員制作模板兩項(xiàng)工作同時(shí)進(jìn)行的效率是最高的,遠(yuǎn)勝于讓一個(gè)人等待另一個(gè)人完成對某個(gè)既包含 Python又包含 HTML 的文件的編輯工作。
基于這些原因,將頁面的設(shè)計(jì)和Python的代碼分離開會(huì)更干凈簡潔更容易維護(hù)。 我們可以使用 Django的?模板系統(tǒng)?(Template System)來實(shí)現(xiàn)這種模式,這就是本章要具體討論的問題。
------------------------------------------------------------------模板語法------------------------------------------------------------------
一模版的組成
組成:HTML代碼+邏輯控制代碼
二 邏輯控制代碼的組成
1 ?變量(使用雙大括號來引用變量):
語法格式: {{var_name}}------Template和Context對象
?
>>> python manange.py shell (進(jìn)入該django項(xiàng)目的環(huán)境) >>> from django.template import Context, Template >>> t = Template('My name is {{ name }}.') >>> c = Context({'name': 'Stephane'}) >>> t.render(c) 'My name is Stephane.'# 同一模板,多個(gè)上下文,一旦有了模板對象,你就可以通過它渲染多個(gè)context,無論何時(shí)我們都可以 # 像這樣使用同一模板源渲染多個(gè)context,只進(jìn)行 一次模板創(chuàng)建然后多次調(diào)用render()方法渲染會(huì) # 更為高效: # Low for name in ('John', 'Julie', 'Pat'):t = Template('Hello, {{ name }}')print t.render(Context({'name': name}))# Good t = Template('Hello, {{ name }}') for name in ('John', 'Julie', 'Pat'):print t.render(Context({'name': name}))?
?Django 模板解析非常快捷。 大部分的解析工作都是在后臺(tái)通過對簡短正則表達(dá)式一次性調(diào)用來完成。 這和基于 XML 的模板引擎形成鮮明對比,那些引擎承擔(dān)了 XML 解析器的開銷,且往往比 Django 模板渲染引擎要慢上幾個(gè)數(shù)量級。
from django.shortcuts import render,HttpResponse from django.template.loader import get_template #記得導(dǎo)入 # Create your views here.import datetime from django.template import Template,Context# def current_time(req):#原始的視圖函數(shù)# now=datetime.datetime.now()# html="<html><body>現(xiàn)在時(shí)刻:<h1>%s.</h1></body></html>" %now# return HttpResponse(html)# def current_time(req):#django模板修改的視圖函數(shù) # now=datetime.datetime.now() # t=Template('<html><body>現(xiàn)在時(shí)刻是:<h1 style="color:red">{{current_date}}</h1></body></html>')#t=get_template('current_datetime.html') # c=Context({'current_date':now}) # html=t.render(c) # return HttpResponse(html)#另一種寫法(推薦)def current_time(req):now=datetime.datetime.now()return render(req, 'current_datetime.html', {'current_date':now})推薦方式-----深度變量的查找(萬能的句點(diǎn)號)
在到目前為止的例子中,我們通過 context 傳遞的簡單參數(shù)值主要是字符串,然而,模板系統(tǒng)能夠非常簡潔地處理更加復(fù)雜的數(shù)據(jù)結(jié)構(gòu),例如list、dictionary和自定義的對象。
在 Django 模板中遍歷復(fù)雜數(shù)據(jù)結(jié)構(gòu)的關(guān)鍵是句點(diǎn)字符 (.)。
#最好是用幾個(gè)例子來說明一下。 # 首先,句點(diǎn)可用于訪問列表索引,例如:>>> from django.template import Template, Context >>> t = Template('Item 2 is {{ items.2 }}.') >>> c = Context({'items': ['apples', 'bananas', 'carrots']}) >>> t.render(c) 'Item 2 is carrots.'#假設(shè)你要向模板傳遞一個(gè) Python 字典。 要通過字典鍵訪問該字典的值,可使用一個(gè)句點(diǎn): >>> from django.template import Template, Context >>> person = {'name': 'Sally', 'age': '43'} >>> t = Template('{{ person.name }} is {{ person.age }} years old.') >>> c = Context({'person': person}) >>> t.render(c) 'Sally is 43 years old.'#同樣,也可以通過句點(diǎn)來訪問對象的屬性。 比方說, Python 的 datetime.date 對象有 #year 、 month 和 day 幾個(gè)屬性,你同樣可以在模板中使用句點(diǎn)來訪問這些屬性:>>> from django.template import Template, Context >>> import datetime >>> d = datetime.date(1993, 5, 2) >>> d.year >>> d.month >>> d.day >>> t = Template('The month is {{ date.month }} and the year is {{ date.year }}.') >>> c = Context({'date': d}) >>> t.render(c) 'The month is 5 and the year is 1993.'# 這個(gè)例子使用了一個(gè)自定義的類,演示了通過實(shí)例變量加一點(diǎn)(dots)來訪問它的屬性,這個(gè)方法適 # 用于任意的對象。 >>> from django.template import Template, Context >>> class Person(object): ... def __init__(self, first_name, last_name): ... self.first_name, self.last_name = first_name, last_name >>> t = Template('Hello, {{ person.first_name }} {{ person.last_name }}.') >>> c = Context({'person': Person('John', 'Smith')}) >>> t.render(c) 'Hello, John Smith.'# 點(diǎn)語法也可以用來引用對象的方法。 例如,每個(gè) Python 字符串都有 upper() 和 isdigit() # 方法,你在模板中可以使用同樣的句點(diǎn)語法來調(diào)用它們: >>> from django.template import Template, Context >>> t = Template('{{ var }} -- {{ var.upper }} -- {{ var.isdigit }}') >>> t.render(Context({'var': 'hello'})) 'hello -- HELLO -- False' >>> t.render(Context({'var': '123'})) '123 -- 123 -- True'# 注意這里調(diào)用方法時(shí)并* 沒有* 使用圓括號 而且也無法給該方法傳遞參數(shù);你只能調(diào)用不需參數(shù)的 # 方法。-----變量的過濾器(filter)的使用
語法格式: {{obj|filter:param}} # 1 add : 給變量加上相應(yīng)的值## 2 addslashes : 給變量中的引號前加上斜線## 3 capfirst : 首字母大寫## 4 cut : 從字符串中移除指定的字符## 5 date : 格式化日期字符串## 6 default : 如果值是False,就替換成設(shè)置的默認(rèn)值,否則就是用本來的值## 7 default_if_none: 如果值是None,就替換成設(shè)置的默認(rèn)值,否則就使用本來的值#實(shí)例:#value1="aBcDe" {{ value1|upper }}<br>#value2=5 {{ value2|add:3 }}<br>#value3='he llo wo r ld' {{ value3|cut:' ' }}<br>#import datetime #value4=datetime.datetime.now() {{ value4|date:'Y-m-d' }}<br>#value5=[] {{ value5|default:'空的' }}<br>#value6='<a href="#">跳轉(zhuǎn)</a>'{{ value6 }}{% autoescape off %}{{ value6 }} {% endautoescape %}{{ value6|safe }}<br>{{ value6|striptags }}#value7='1234' {{ value7|filesizeformat }}<br> {{ value7|first }}<br> {{ value7|length }}<br> {{ value7|slice:":-1" }}<br>#value8='http://www.baidu.com/?a=1&b=3' {{ value8|urlencode }}<br>value9='hello I am yuan'2 標(biāo)簽(tag)的使用(使用大括號和百分比的組合來表示使用tag)
{% tags %}------{% if %} 的使用?
{% if %}標(biāo)簽計(jì)算一個(gè)變量值,如果是“true”,即它存在、不為空并且不是false的boolean值,系統(tǒng)則會(huì)顯示{% if %}和{% endif %}間的所有內(nèi)容
{% if num >= 100 and 8 %}{% if num > 200 %}<p>num大于200</p>{% else %}<p>num大于100小于200</p>{% endif %}{% elif num < 100%}<p>num小于100</p>{% else %}<p>num等于100</p>{% endif %}{% if %} 標(biāo)簽接受and,or或者not來測試多個(gè)變量值或者否定一個(gè)給定的變量 {% if %} 標(biāo)簽不允許同一標(biāo)簽里同時(shí)出現(xiàn)and和or,否則邏輯容易產(chǎn)生歧義,例如下面的標(biāo)簽是不合法的:{% if obj1 and obj2 or obj3 %}------{% for %}的使用
{% for %}標(biāo)簽允許你按順序遍歷一個(gè)序列中的各個(gè)元素,每次循環(huán)模板系統(tǒng)都會(huì)渲染{% for %}和{% endfor %}之間的所有內(nèi)容
<ul> {% for obj in list %}<li>{{ obj.name }}</li> {% endfor %} </ul>#在標(biāo)簽里添加reversed來反序循環(huán)列表:{% for obj in list reversed %}...{% endfor %}#{% for %}標(biāo)簽可以嵌套:{% for country in countries %}<h1>{{ country.name }}</h1><ul>{% for city in country.city_list %}<li>{{ city }}</li>{% endfor %}</ul>{% endfor %}#系統(tǒng)不支持中斷循環(huán),系統(tǒng)也不支持continue語句,{% for %}標(biāo)簽內(nèi)置了一個(gè)forloop模板變量, #這個(gè)變量含有一些屬性可以提供給你一些關(guān)于循環(huán)的信息1,forloop.counter表示循環(huán)的次數(shù),它從1開始計(jì)數(shù),第一次循環(huán)設(shè)為1:{% for item in todo_list %}<p>{{ forloop.counter }}: {{ item }}</p>{% endfor %} 2,forloop.counter0 類似于forloop.counter,但它是從0開始計(jì)數(shù),第一次循環(huán)設(shè)為0 3,forloop.revcounter 4,forloop.revcounter0 5,forloop.first當(dāng)?shù)谝淮窝h(huán)時(shí)值為True,在特別情況下很有用:{% for object in objects %} {% if forloop.first %}<li class="first">{% else %}<li>{% endif %} {{ object }} </li> {% endfor %} # 富有魔力的forloop變量只能在循環(huán)中得到,當(dāng)模板解析器到達(dá){% endfor %}時(shí)forloop就消失了 # 如果你的模板context已經(jīng)包含一個(gè)叫forloop的變量,Django會(huì)用{% for %}標(biāo)簽替代它 # Django會(huì)在for標(biāo)簽的塊中覆蓋你定義的forloop變量的值 # 在其他非循環(huán)的地方,你的forloop變量仍然可用#{% empty %}{{li }}{% for i in li %}<li>{{ forloop.counter0 }}----{{ i }}</li>{% empty %}<li>this is empty!</li>{% endfor %}# [11, 22, 33, 44, 55] # 0----11 # 1----22 # 2----33 # 3----44 # 4----55------{%csrf_token%}:csrf_token標(biāo)簽
? ? ?用于生成csrf_token的標(biāo)簽,用于防治跨站攻擊驗(yàn)證。注意如果你在view的index里用的是render_to_response方法,不會(huì)生效
???? 其實(shí),這里是會(huì)生成一個(gè)input標(biāo)簽,和其他表單標(biāo)簽一起提交給后臺(tái)的。
------{% url %}: ?引用路由配置的地址
?
<form action="{% url "bieming"%}" ><input type="text"><input type="submit"value="提交">{%csrf_token%} </form>?
------{% with %}:用更簡單的變量名替代復(fù)雜的變量名
?
{% with total=fhjsaldfhjsdfhlasdfhljsdal %} {{ total }} {% endwith %}?
------{% verbatim %}: 禁止render
?
{% verbatim %}{{ hello }}{% endverbatim %}?
-----{% load %}:?加載標(biāo)簽庫
3 自定義filter和simple_tag
------a、在app中創(chuàng)建templatetags模塊(必須的)
------b、創(chuàng)建任意 .py 文件,如:my_tags.py
?
from django import template from django.utils.safestring import mark_saferegister = template.Library() #register的名字是固定的,不可改變@register.filter def filter_multi(v1,v2):return v1 * v2@register.simple_tag def simple_tag_multi(v1,v2):return v1 * v2@register.simple_tag def my_input(id,arg):result = "<input type='text' id='%s' class='%s' />" %(id,arg,)return mark_safe(result)?
------c、在使用自定義simple_tag和filter的html文件中導(dǎo)入之前創(chuàng)建的 my_tags.py :{% load my_tags %}
------d、使用simple_tag和filter(如何調(diào)用)
?
-------------------------------.html {% load xxx %} #首行# num=12 {{ num|filter_multi:2 }} #24{{ num|filter_multi:"[22,333,4444]" }}{% simple_tag_multi 2 5 %} 參數(shù)不限,但不能放在if for語句中 {% simple_tag_multi num 5 %}?
-----e、在settings中的INSTALLED_APPS配置當(dāng)前app,不然django無法找到自定義的simple_tag.
注意:
filter可以用在if等語句后,simple_tag不可以
{% if num|filter_multi:30 > 100 %}{{ num|filter_multi:30 }} {% endif %}4 extend模板繼承
------include?模板標(biāo)簽
在講解了模板加載機(jī)制之后,我們再介紹一個(gè)利用該機(jī)制的內(nèi)建模板標(biāo)簽:?{%?include?%}?。該標(biāo)簽允許在(模板中)包含其它的模板的內(nèi)容。 標(biāo)簽的參數(shù)是所要包含的模板名稱,可以是一個(gè)變量,也可以是用單/雙引號硬編碼的字符串。 每當(dāng)在多個(gè)模板中出現(xiàn)相同的代碼時(shí),就應(yīng)該考慮是否要使用?{%?include?%}?來減少重復(fù)。
------extend(繼承)模板標(biāo)簽
到目前為止,我們的模板范例都只是些零星的 HTML 片段,但在實(shí)際應(yīng)用中,你將用 Django 模板系統(tǒng)來創(chuàng)建整個(gè) HTML 頁面。 這就帶來一個(gè)常見的 Web 開發(fā)問題: 在整個(gè)網(wǎng)站中,如何減少共用頁面區(qū)域(比如站點(diǎn)導(dǎo)航)所引起的重復(fù)和冗余代碼?
解決該問題的傳統(tǒng)做法是使用?服務(wù)器端的 includes?,你可以在 HTML 頁面中使用該指令將一個(gè)網(wǎng)頁嵌入到另一個(gè)中。 事實(shí)上, Django 通過剛才講述的?{%?include?%}?支持了這種方法。 但是用 Django 解決此類問題的首選方法是使用更加優(yōu)雅的策略——?模板繼承?。
本質(zhì)上來說,模板繼承就是先構(gòu)造一個(gè)基礎(chǔ)框架模板,而后在其子模板中對它所包含站點(diǎn)公用部分和定義塊進(jìn)行重載。
讓我們通過修改?current_datetime.html?文件,為?current_datetime?創(chuàng)建一個(gè)更加完整的模板來體會(huì)一下這種做法:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"> <html lang="en"> <head><title>The current time</title> </head> <body><h1>My helpful timestamp site</h1><p>It is now {{ current_date }}.</p><hr><p>Thanks for visiting my site.</p> </body> </html>這看起來很棒,但如果我們要為?hours_ahead?視圖創(chuàng)建另一個(gè)模板會(huì)發(fā)生什么事情呢?
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"> <html lang="en"> <head><title>Future time</title> </head> <body><h1>My helpful timestamp site</h1><p>In {{ hour_offset }} hour(s), it will be {{ next_time }}.</p><hr><p>Thanks for visiting my site.</p> </body> </html>很明顯,我們剛才重復(fù)了大量的 HTML 代碼。 想象一下,如果有一個(gè)更典型的網(wǎng)站,它有導(dǎo)航條、樣式表,可能還有一些 JavaScript 代碼,事情必將以向每個(gè)模板填充各種冗余的 HTML 而告終。
解決這個(gè)問題的服務(wù)器端 include 方案是找出兩個(gè)模板中的共同部分,將其保存為不同的模板片段,然后在每個(gè)模板中進(jìn)行 include。 也許你會(huì)把模板頭部的一些代碼保存為?header.html?文件:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"> <html lang="en"> <head>你可能會(huì)把底部保存到文件?footer.html?:
<hr><p>Thanks for visiting my site.</p> </body> </html>對基于 include 的策略,頭部和底部的包含很簡單。 麻煩的是中間部分。 在此范例中,每個(gè)頁面都有一個(gè)<h1>My?helpful?timestamp?site</h1>?標(biāo)題,但是這個(gè)標(biāo)題不能放在?header.html?中,因?yàn)槊總€(gè)頁面的?<title>?是不同的。 如果我們將?<h1>?包含在頭部,我們就不得不包含?<title>?,但這樣又不允許在每個(gè)頁面對它進(jìn)行定制。 何去何從呢?
Django 的模板繼承系統(tǒng)解決了這些問題。 你可以將其視為服務(wù)器端 include 的逆向思維版本。 你可以對那些不同?的代碼段進(jìn)行定義,而不是?共同?代碼段。
第一步是定義?基礎(chǔ)模板,該框架之后將由子模板所繼承。 以下是我們目前所講述范例的基礎(chǔ)模板:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"> <html lang="en"> <head><title>{% block title %}{% endblock %}</title> </head> <body><h1>My helpful timestamp site</h1>{% block content %}{% endblock %}{% block footer %}<hr><p>Thanks for visiting my site.</p>{% endblock %} </body> </html>這個(gè)叫做?base.html?的模板定義了一個(gè)簡單的 HTML 框架文檔,我們將在本站點(diǎn)的所有頁面中使用。 子模板的作用就是重載、添加或保留那些塊的內(nèi)容。 (如果你一直按順序?qū)W習(xí)到這里,保存這個(gè)文件到你的template目錄下,命名為?base.html?.)
我們使用模板標(biāo)簽:?{%?block?%}?。 所有的?{%?block?%}?標(biāo)簽告訴模板引擎,子模板可以重載這些部分。 每個(gè){%?block?%}標(biāo)簽所要做的是告訴模板引擎,該模板下的這一塊內(nèi)容將有可能被子模板覆蓋。
現(xiàn)在我們已經(jīng)有了一個(gè)基本模板,我們可以修改?current_datetime.html?模板來 使用它:
{% extends "base.html" %}{% block title %}The current time{% endblock %}{% block content %} <p>It is now {{ current_date }}.</p> {% endblock %}再為?hours_ahead?視圖創(chuàng)建一個(gè)模板,看起來是這樣的:
{% extends "base.html" %}{% block title %}Future time{% endblock %}{% block content %} <p>In {{ hour_offset }} hour(s), it will be {{ next_time }}.</p> {% endblock %}看起來很漂亮是不是? 每個(gè)模板只包含對自己而言?獨(dú)一無二?的代碼。 無需多余的部分。 如果想進(jìn)行站點(diǎn)級的設(shè)計(jì)修改,僅需修改?base.html?,所有其它模板會(huì)立即反映出所作修改。
????? 以下是其工作方式:
????? 在加載?current_datetime.html?模板時(shí),模板引擎發(fā)現(xiàn)了?{%?extends?%}?標(biāo)簽, 注意到該模板是一個(gè)子模板。 模板引擎立即裝載其父模板,即本例中的?base.html?。此時(shí),模板引擎注意到?base.html?中的三個(gè)?{%?block?%}?標(biāo)簽,并用子模板的內(nèi)容替換這些 block 。因此,引擎將會(huì)使用我們在?{?block?title?%}?中定義的標(biāo)題,對?{%?block?content?%}?也是如此。 所以,網(wǎng)頁標(biāo)題一塊將由{%?block?title?%}替換,同樣地,網(wǎng)頁的內(nèi)容一塊將由?{%?block?content?%}替換。
???? 注意由于子模板并沒有定義?footer?塊,模板系統(tǒng)將使用在父模板中定義的值。 父模板?{%?block?%}?標(biāo)簽中的內(nèi)容總是被當(dāng)作一條退路。繼承并不會(huì)影響到模板的上下文。 換句話說,任何處在繼承樹上的模板都可以訪問到你傳到模板中的每一個(gè)模板變量。你可以根據(jù)需要使用任意多的繼承次數(shù)。 使用繼承的一種常見方式是下面的三層法:
<1> 創(chuàng)建 base.html 模板,在其中定義站點(diǎn)的主要外觀感受。 這些都是不常修改甚至從不修改的部分。<2> 為網(wǎng)站的每個(gè)區(qū)域創(chuàng)建 base_SECTION.html 模板(例如, base_photos.html 和 base_forum.html )。這些模板對base.html 進(jìn)行拓展,并包含區(qū)域特定的風(fēng)格與設(shè)計(jì)。<3> 為每種類型的頁面創(chuàng)建獨(dú)立的模板,例如論壇頁面或者圖片庫。 這些模板拓展相應(yīng)的區(qū)域模板。?這個(gè)方法可最大限度地重用代碼,并使得向公共區(qū)域(如區(qū)域級的導(dǎo)航)添加內(nèi)容成為一件輕松的工作。
以下是使用模板繼承的一些訣竅:
<1>如果在模板中使用 {% extends %} ,必須保證其為模板中的第一個(gè)模板標(biāo)記。 否則,模板繼承將不起作用。<2>一般來說,基礎(chǔ)模板中的 {% block %} 標(biāo)簽越多越好。 記住,子模板不必定義父模板中所有的代碼塊,因此你可以用合理的缺省值對一些代碼塊進(jìn)行填充,然后只對子模板所需的代碼塊進(jìn)行(重)定義。 俗話說,鉤子越多越好。<3>如果發(fā)覺自己在多個(gè)模板之間拷貝代碼,你應(yīng)該考慮將該代碼段放置到父模板的某個(gè) {% block %} 中。如果你需要訪問父模板中的塊的內(nèi)容,使用 {{ block.super }}這個(gè)標(biāo)簽吧,這一個(gè)魔法變量將會(huì)表現(xiàn)出父模板中的內(nèi)容。 如果只想在上級代碼塊基礎(chǔ)上添加內(nèi)容,而不是全部重載,該變量就顯得非常有用了。<4>不允許在同一個(gè)模板中定義多個(gè)同名的 {% block %} 。 存在這樣的限制是因?yàn)閎lock 標(biāo)簽的工作方式是雙向的。也就是說,block 標(biāo)簽不僅挖了一個(gè)要填的坑,也定義了在父模板中這個(gè)坑所填充的內(nèi)容。如果模板中出現(xiàn)了兩個(gè)相同名稱的 {% block %} 標(biāo)簽,父模板將無從得知要使用哪個(gè)塊的內(nèi)容。?
轉(zhuǎn)載于:https://www.cnblogs.com/huangjinshan/p/6479929.html
總結(jié)
以上是生活随笔為你收集整理的Django Views(视图函数)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: xmlhttprequest level
- 下一篇: 付费率第一 亏损显著收窄 网易云音乐将实