1.Django請求和返回周期Django默認使用wsgiref模塊但是該模塊并發(fā)量特別小(大約1000),不適用于線上環(huán)境,所以在Django項目上線之后會使用uwsgi。1.1路由層之路由匹配主要是在ursl.py文件里書寫。1.11版
1. Django 請求和返回周期
Django默認使用wsgiref模塊但是該模塊并發(fā)量特別小(大約1000),不適用于線上環(huán)境,所以在Django項目上線之后會使用uwsgi。
1.1 路由層之路由匹配
主要是在ursl.py文件里書寫。
1.11版本: urlpatterns = [ url( '^admin/ ', admin.site.urls), ] 3.2版本: urlpatterns = [ path( 'admin/ ', admin.site.urls), path( 'test/ ', views.test), path( 'testadd/ ', views.testadd), ] 1版本中使用url方法: url()方法: 1,第一個參數(shù)為一個正則 2,只要能匹配上就會執(zhí)行后面的視圖函數(shù) 3版本中使用path path()方法 第一個參數(shù)是一個字符串 如果使用正則,則要使用 re_path() 而不是 path() 。 urlpatterns = [ re_path(r '^admin/ ', admin.site.urls), ] test/和testadd/ 在匹配的時候如果不寫后面的斜杠(/),發(fā)現(xiàn)也能匹配上,是因為Django在做的時候如果test匹配不上,它會讓瀏覽器后面自動加上斜杠(/)再試一次。 這個是用settings里面的APPEND_SLASH參數(shù)控制,默認為True,如果只想匹配一次則設(shè)置為False. APPEND_SLASH=False
在Django3.x在匹配時有了路徑轉(zhuǎn)換器:
str - 匹配除了 '/ ' 之外的非空字符串。如果表達式內(nèi)不包含轉(zhuǎn)換器,則會默認匹配字符串。
int - 匹配 0 或任何正整數(shù)。返回一個 int 。 path( 'articles// ', views.year_archive), 是個整型參數(shù)
slug - 匹配任意由 ASCII 字母或數(shù)字以及連字符和下劃線組成的短標簽。比如,building-your-1st-django-site 。
uuid - 匹配一個格式化的 UUID 。為了防止多個 URL 映射到同一個頁面,必須包含破折號并且字符都為小寫。比如,075194d3-6885-417e-a8a8-6c931e272f00。返回一個 UUID 實例。
path - 匹配非空字段,包括路徑分隔符 '/ ' 。它允許你匹配完整的 URL 路徑而不是像 str 那樣匹配 URL 的一部分。
1.2 有名分組
命名正則表達式組的語法是 (?Ppattern) 其中 name 是組名,pattern 是要匹配的模式
在Django3中路由匹配使用正則: ursl.py文件: from django.co ntrib im port admin from django.urls im port path,re_path #要手動導(dǎo)入re_path from orm im port views urlpatterns = [ path( 'admin/ ', admin.site.urls), path( 'test/ ', views.test), path( 'testadd/ ', views.testadd), re_path(r 'test/(?P[0-9]{4})/ ', views.testadd), ] 在views.py: def testadd(request,year): print(year) return HttpRespo nse( "from test ") // 分組名必須要傳給后面的視圖函數(shù),否則會報錯。 如上面的例子,分組名為year,如果不傳給后端的views.testadd函數(shù),報錯信息: testadd() got an unexpected keyword argument 'year ' 有名分組 將括號內(nèi)正則表達式匹配到的內(nèi)容當做關(guān)鍵字參數(shù)傳遞給后面的視圖函數(shù)
1.3 無名分組
有命名組語法,例如 (?P[0-9]{4}) ,你也可以使用更短的未命名組,例如 ([0-9]{4}) 。
在Django3中路由匹配使用正則: ursl.py文件: from django.co ntrib im port admin from django.urls im port path,re_path #要手動導(dǎo)入re_path from orm im port views urlpatterns = [ path( 'admin/ ', admin.site.urls), path( 'test/ ', views.test), path( 'testadd/ ', views.testadd), re_path(r 'test/([0-9]{4})/#39;, views.test), ] 啟動訪問: http://127.0.0.1:8000/test/1234/ 報錯: test() takes 1 positio nal argument but 2 were given 解決方法: 在views.py: def test(request,what): print(what) return HttpRespo nse( "from test ") 再執(zhí)行訪問成功。 控制臺打印的結(jié)果: 1234 無名分組: 將括號內(nèi)正則表達式匹配到的內(nèi)容當做位置參數(shù)傳遞給后面的視圖函數(shù)。
總結(jié):
有名分組和無名分組不能混合使用。 單個種類可以重復(fù)使用 2. 反射解析
當路由頻繁變化的時候,HTML界面上的連接地址如何做到動態(tài)解析。
" " " 1. 給路由與視圖函數(shù)對應(yīng)關(guān)系添加一個別名(名字自己定義,名字之間不要沖突) path( 'show/ ', views.show, name= 'showtime '), 2. 根據(jù)這個別名動態(tài)解析出一個結(jié)果,該結(jié)果可以直接訪問到對應(yīng)的路由 前端使用別名: "{% url 'showtime ' %} ">Hello Django 這樣不管path里面的show怎么變,只要name= 'showtime '不變,那么訪問就沒問題 后端使用別名: ursl.py: urlpatterns = [ path( 'show/ ', views.show, name= 'showtime '), ] views.py from django.shortcuts im port render, HttpResponse,redirect,reverse def delet e(request): ...... print(revers e( 'showtime ')) # 打印url return redirect( 'showtime ') # 也可以直接在重定向里寫別名 " " "
無名和有名分組指向解析
ursl.py " " " from django.urls im port path,re_path urlpatterns = [ re_path(r 'test/([0-9]{4})/#39;, views.test, name= 'index_test '), ] " " " views.py " " " def delet e(request): ...... print(revers e( 'index_test ',args=(1,))) # 打印url args=(1,) args后面跟一個元組,里面這寫的是1,推薦寫主鍵的值 r 'test/([0-9]{4})/([0-9]{4})/$ 如果有兩個分組,則args后面必須寫兩個值,(1,2)第二個值可以隨便寫 " " " 前端也一樣: "{% url 'index_test ' 123 %} ">Hello Django 這里123也是隨便寫的,只要寫個數(shù)字就行 有名: 后端 revers e( 'index_test ',kwargs={ 'id ':123}) 前端 "{% url 'index_test ' id=123 %} ">Hello Django
總結(jié)
無名和有名都可以使用一種(無名)反向解析的形式
3. 路由分發(fā)
其實Django中的每一個應(yīng)用都可以有自己的urls.py、static文件夾、templates文件夾,這樣使用Django做分組開發(fā)非常的簡便。每個人只需要寫息的應(yīng)用即可,最后匯總到一個空的Django項目中然后使用路由分發(fā) 將多個應(yīng)用關(guān)聯(lián)。
示例:
創(chuàng)建一個項目,并創(chuàng)建兩個應(yīng)用(app01,app02). 在每個應(yīng)用里面都創(chuàng)建一個urls.py文件。 app01 urls.py: " " " from django.urls im port path from app01 im port views urlpatterns = [ path( 'index ', views.index), ] " " " app01 views.py: " " " from django.shortcuts im port render,HttpRespo nse # Create your views here. def index(request): return HttpRespo nse( "from app01 index ") " " " app02 urls.py: " " " from django.urls im port path from app02 im port views urlpatterns = [ path( 'index ', views.index), ] " " " app02 views.py: " " " from django.shortcuts im port render,HttpRespo nse # Create your views here. def index(request): return HttpRespo nse( "from app02 index ") " " " 項目中總的urls.py: " " " from django.co ntrib im port admin from django.urls im port path,include # 導(dǎo)入應(yīng)用的urls from app01 im port urls as app01_urls from app02 im port urls as app02_urls urlpatterns = [ path( 'admin/ ', admin.site.urls), path( 'app01/ ', include(app01_urls)), path( 'app02/ ', include(app02_urls)), ] " " " 注意: 需要在總的urls.py里導(dǎo)入include from django.urls im port path,include 在總的路由里面不能加$符號,否則沒辦法分發(fā) 還有一種在總的urls.py里不需要導(dǎo)入應(yīng)用urlsr 的方法: 項目中總的urls.py: " " " from django.co ntrib im port admin from django.urls im port path,include urlpatterns = [ path( 'admin/ ', admin.site.urls), path( 'app01/ ', include( 'app01.urls ')), path( 'app02/ ', include( 'app02.urls ')), ] " " "
4 名稱空間
當多個應(yīng)用在反射解析的時候如果出現(xiàn)了別名沖突的情況,那么將會無法自動識別
示例:
app01 urls.py: " " " from django.urls im port path from app01 im port views urlpatterns = [ path( 'index ', views.index,name= 'index_name '), path( 'login ', views.login) ] " " " app01 views.py: " " " from django.shortcuts im port render,HttpResponse,reverse # Create your views here. def index(request): return HttpRespo nse( "from app01 index ") def login(request): print(revers e( 'index_name ')) return HttpRespo nse( "from app01 login ") " " " app02 urls.py: " " " from django.urls im port path from app02 im port views urlpatterns = [ path( 'index ', views.index,name= 'index_name '), path( 'login ', views.login), ] " " " app02 views.py: " " " from django.shortcuts im port render,HttpResponse,reverse # Create your views here. def index(request): return HttpRespo nse( "from app02 index ") def login(request): print(revers e( 'index_name ')) return HttpRespo nse( "from app02 login ") " " " 項目中總的urls.py: " " " from django.co ntrib im port admin from django.urls im port path,include urlpatterns = [ path( 'admin/ ', admin.site.urls), path( 'app01/ ', include( 'app01.urls ')), path( 'app02/ ', include( 'app02.urls ')), ] " " " 雖然訪問頁面: http://127.0.0.1:8000/app01/login http://127.0.0.1:8000/app02/login 的時候能正常拿到對應(yīng)的頁面,但是在后端發(fā)現(xiàn)拿到的是同一個: /app02/index /app02/index
要解決這個問題就用到了名稱空間
解決方法一:使用名稱空間
在總路上加上namespace這個參數(shù): 項目中總的urls.py: " " " from django.co ntrib im port admin from django.urls im port path,include urlpatterns = [ path( 'admin/ ', admin.site.urls), path( 'app01/ ', include( 'app01.urls ',namespace= 'app01 ')), path( 'app02/ ', include( 'app02.urls ',namespace= 'app02 ')), ] " " " app01 urls.py: " " " from django.urls im port path from app01 im port views app_name= 'app01 ' urlpatterns = [ path( 'index ', views.index,name= 'index_name '), path( 'login ', views.login) ] " " " app01 views.py: " " " from django.shortcuts im port render,HttpResponse,reverse # Create your views here. def index(request): return HttpRespo nse( "from app01 index ") def login(request): print(revers e( 'app01:index_name ')) return HttpRespo nse( "from app01 login ") " " " app02 urls.py: " " " from django.urls im port path from app02 im port views app_name= 'app02 ' urlpatterns = [ path( 'index ', views.index,name= 'index_name '), path( 'login ', views.login), ] " " " app02 views.py: " " " from django.shortcuts im port render,HttpResponse,reverse # Create your views here. def index(request): return HttpRespo nse( "from app02 index ") def login(request): print(revers e( 'app02:index_name ')) return HttpRespo nse( "from app02 login ") " " " 訪問頁面: http://127.0.0.1:8000/app01/login http://127.0.0.1:8000/app02/login 拿到的就是 /app01/index /app02/index 注意在Django3.2版本中使用名稱空間的時候,一定要給每個應(yīng)用設(shè)置應(yīng)用名,否則會報錯: ' ' 'pecifying a namespace in include() without providing an app_name is not supported. Set the app_name attribute in the included module, or pass a 2-tuple co ntaining the list of patterns and app_name instead. ' ' ' 解決方法: app01 urls.py: ' ' ' app_name= 'app01 ' ' ' ' app02 urls.py: ' ' 'app_name= 'app02 ' ' ' ' 這兩個必須要設(shè)置。
前端使用名稱空間:
"{% url 'app01:index_name ' %} ">app01_index "{% url 'app02:index_name ' %} ">app02_index
注意:
雖然我們現(xiàn)在可以將模板文件直接放在 app01/templates 文件夾中(而不是再建立一個 app01 子文件夾),但是這樣做不太好。Django 將會選擇第一個匹配的模板文件,如果你有一個模板文件正好和另一個應(yīng)用中的某個模板文件重名,Django 沒有辦法 區(qū)分 它們。我們需要幫助 Django 選擇正確的模板,最好的方法就是把他們放入各自的 命名空間 中,也就是把這些模板放入一個和 自身 應(yīng)用重名的子文件夾里。(app01/templates/app01/login.html)
同理:多個應(yīng)用下的靜態(tài)文件也是這樣。
所以在前端使用名稱空間的時候,HTML文件的路徑為:
app01/templates/app01/login.html app02/templates/app02/login.html 后端app01 views.py: from django.shortcuts im port render,HttpResponse,reverse def login(request): print(revers e( 'app01:index_name ')) return render(request, "app01/login.html ") 后端app02 views.py: from django.shortcuts im port render,HttpResponse,reverse def login(request): print(revers e( 'app02:index_name ')) return render(request, "app02/login.html ")
解決方法二:別名別沖突
寫別名的時候要加上自己應(yīng)用名做前綴。
5. JsonResponse
給前端返回一個json格式的數(shù)據(jù)
方法一:自己序列化
views.py: from django.shortcuts im port render,HttpResponse,reverse im port json def index(request): d = { 'user ': 'Hans ', 'password ':123} d_json = json.dumps(d) return HttpRespo nse(d_json) # json默認不能直接識別的字符直接返回對應(yīng)的unicode編碼,如上面的漢字要正確返回則需要設(shè)置ensure_ascii=False d = { 'user ': 'Hans你好 ', 'password ':123} d_json = json.dumps(d,ensure_ascii=False)
方法二: 使用JsonResponse
views.py: from django.shortcuts im port render,HttpResponse,reverse from django.http im port Jso nResponse def index(request): d = { 'user ': 'Hans ', 'password ':123} return Jso nResponse(d) # Jso nResponse 對不能識別的字符也是直接返回unicode編碼,如果對漢字也能正常展示,加上json_dumps_params={ 'ensure_ascii ':False}參數(shù): d = { 'user ': 'Hans你好 ', 'password ':123} return Jso nResponse(d,json_dumps_params={ 'ensure_ascii ':False}) # 如果序列化一個非字典類型的,則需要讓safe=False 如: li = [ 'A ', 'B ', 'C '] return Jso nResponse(d, safe=Fasle)
6. 上傳文件
前端頁面: # 路由層: path( 'upfile ', views.upfile), # 視圖層 views.py: from django.shortcuts im port render,HttpResponse,reverse def upfile(request): if request.method == 'POST ': file_obj = request.FILES.get( 'files ') print(file_obj.name) with open(r './app01/templates/%s ' % file_obj.name, 'wb ') as f: for chunk in file_obj.chunks(): f.write(chunk) return render(request, "app01/upfile.html ")
7. FBV和CBV
FBV:基于函數(shù)的視圖
CBV:基于類的視圖
上面寫的都為FBV,基于函數(shù)的視圖,現(xiàn)在寫一個基于類的視圖。
# views.py from django.shortcuts im port render,HttpResponse,reverse from django.views im port View class MyView(View): def get(self,request): return HttpRespo nse( "GET方法 ") def pos(self,request): return HttpRespo nse( "POST方法 ") # urls.py from django.urls im port path from . im port views urlpatterns = [ path( 'myview ', views.MyView.as_view()), ] #CBV和FBV路由匹配其實是一樣的。
8. 模板語法傳值
8.1 傳基本數(shù)據(jù)類型
# 方法一:精確傳值 # urls.py " " " from django.co ntrib im port admin from django.urls im port path from templateByValue im port views urlpatterns = [ path( 'admin/ ', admin.site.urls), path( 'index/ ', views.index), ] " " " # 前端HTML: " " " " " " views.py: " " " from django.shortcuts im port render # Create your views here. def index(request): i = 123 f = 12.3 str = "Hello Django " Li = [1, 2, 3] d = { 'username ': "Hans ", "age ":19} t = (1, 2, 3, 4) set01 = {1, 2, 3, 4} bool_value = True return render(request, 'index.html ',{ "i ":i, "f ":f, "str ":str, "Li ":Li, "d ":d, 't ':t, "set01 ":set01, 'bool_value ':bool_value}) " " " # 方法二:使用locals函數(shù) # 在views.py 中給前端頁面?zhèn)髦得總€都要寫,在值特別多的時候不方便,可以使用locals函數(shù) " " " return render(request, "index.html ",locals()) " " " locals() 獲取全部局部變量: { 'request ': '/index/ '>, 'i ': 123, 'f ': 12.3, 'str ': 'Hello Django ', 'Li ': [1, 2, 3], 'd ': { 'username ': 'Hans ', 'age ': 19}, 't ': (1, 2, 3, 4), 'set01 ': {1, 2, 3, 4}, 'bool_value ': True},然后全部傳給前端頁面。 兩者的優(yōu)缺點: 方法一,可以精確傳值,不會造成資源浪費,但傳的值多的時候書寫不方便 方法二, 書寫方便,但是會造成資源浪費。
8.2 傳函數(shù)名
# 前端: " " " {{ foo }}
" " " # views.py: " " " from django.shortcuts im port render # Create your views here. # 定義函數(shù) def index(request): def foo(): print( "hello ") return "Hello Django " return render(request, "index.html ",{ "foo ":foo}) # 給前端傳遞,前面拿到的是函數(shù)的返回值。 " " " 使用模板語法傳函數(shù)的時候,不支持帶參數(shù)
8.3 傳類名
# 前端: " " " {{ MyClass }}
{{ obj }}
{{ obj.get_self }}
{{ obj.get_cls }}
{{ obj.get_static }}
" " " #views.py " " " from django.shortcuts im port render # Create your views here. def index(request): class MyClass(object): def get_self(self): return "綁定給對象的方法 " @classmethod def get_cls(cls): return "綁定給類的方法 " @staticmethod def get_static(): return "普通的函數(shù) " obj = MyClass() print(locals()) return render(request, "index.html ",{ "MyClass ":MyClass, "obj ":obj}) " " " 或直接寫: return render(request, "index.html ",locals())
總結(jié)
傳遞函數(shù)名和類名都會自動加括號調(diào)用(模板語法不支持額外的傳參數(shù))
9. 模板語法獲取值
Django中模板語法取值只用.
# views.py " " " from django.shortcuts im port render # Create your views here. def index(request): Li = [1, 2, 3] d = { 'username ': "Hans ", "age ":19} return render(request, 'index.html ',locals()) " " " # 前端: " " " 拿列表第二個值 拿年齡 " " "
10. 模板語法過濾器
過濾器的符號是管道符:|,將管道符左側(cè)的數(shù)據(jù)當做第一個參數(shù)。
# views.py: " " " from django.shortcuts im port render # Create your views here. def index(request): i = 123 str = "Hello Django " Li = [1, 2, 3] d = { 'username ': "Hans ", "age ":19} bool_value = True bool_var = False im port datetime ctime = datetime.datetime.now() file_size = 409600 h = "Hello " from django.utils.safestring im port mark_safe h1 =mark_safe( "Django ") #后端也可以直接寫HTML語法返回給前端了 return render(request, "index.html ",locals()) " " " # 前端: " " " 過濾器:將管道符左側(cè)的數(shù)據(jù)當做第一個參數(shù)
統(tǒng)計長度:{{ str|length }}
加法:{{ i|add:10000 }}
字符串拼接:{{ str|add: "HAHA " }}
日期格式:{{ ctime|date: "Y-m-d " }}
默認值:{{ bool_value|default: "哈哈 " }}
默認值:{{ bool_var|default: "哈哈 " }}
文件大小:{{ file_size|filesizeformat }}
截取文本(截6個字符,包括3個點):{{ str|truncatechars:6 }}
截取文本(截1個單詞,不包括3個點):{{ str|truncatewords:1 }}
h源信息:{{ h }}
前端把后端傳過來的數(shù)據(jù)(h),格式成HTML格式: {{ h|safe }}
后端傳過來的數(shù)據(jù)(h1)直接為HTML格式顯示: {{ h1 }}
" " "
11. 模板語法標簽(流程控制)
# if {% if var %} good
{% endif %} # if else {% if bool_var %} var
{% else %} valu
{% endif %} # if ... elif ... else {% if bool_var %} var
{% elif bool_value %} value
{% else %} 都沒有
{% endif %} # for {% for foo in Li %} foo
{% endfor %} # for內(nèi)可以嵌套if {% for foo in Li %} foo
{% empty %} # 如果是空的時候,打印empty里的 空值
{% endfor %} # forloop 打印循環(huán)次數(shù) {% for foo in Li %} foo
{{forloop.counter}} {% endfor %} {{}} 變量相關(guān)的用 {%%} 邏輯相關(guān)的用 # with {% with d.3.username as name %} # 給d.3.username起別名 {{ name }} {% endwith %} 這個別名只能在with里面用。
12. 自定義過濾器、標簽、inclusion_tag
類似于python里面的自定義函數(shù)
1. 在應(yīng)用下創(chuàng)建一個名字必須叫 "templatetags "文件夾 2, 在上述文件夾內(nèi)創(chuàng)建一個任意名稱的py文件 3, 在該py文件內(nèi)固定寫入: from django im port template register = template.Library()
12.1 自定義過濾器:
示例:
1,在應(yīng)用下創(chuàng)建templatetags文件夾 2,在templatetags夾里創(chuàng)建myFilter.py 文件內(nèi)容: " " " from django im port template register = template.Library() @register.filter(name= "My ") # 過濾器名 def index(a,b): return a+b " " " 3, views.py from django.shortcuts im port render def index(request): i = 123 return render(request, "index.html ",locals()) 4,前端頁面: {% load myFilter %}
{{ i |My:100}}
5. 瀏覽器顯示結(jié)果: 223
過濾器只能接受兩個參數(shù)。
12.2 自定義標簽
1, 依然是在myFilter.py文件里: " " " from django im port template register = template.Library() @register.simple_tag(name= 'myTag ') # 標簽名 def foo(a,b,c,d): return "{%s:%s %s:%s} " % (a,b,c,d) " " " 2, 前端頁面: " " " {% load myFilter %} {% myTag 1 "hans " 2 "Hello " %} # 標簽傳值使用空格分隔
" " "
標簽可以接受多個參數(shù)
12.3 自定義inclusion_tag
前面自定義的過濾器和標簽,都是自定義的過濾器函數(shù)和標簽函數(shù)直接返回給前端,自定義inclusion_tag有些不同。
在myFilter.py文件里: from django im port template register = template.Library() @register.inclusion_tag( 'login.html ', name= "myInclusion ") # inclusion_tag名字 def foo2(n): l =[] for i in range(1, n+1): l.append( "第%s頁 " % i) return locals() # login.html {% for foo in l %} {{ foo }} {% endfor %} # 前端頁面: {% load myFilter %} {% myInclusion 4 %}
結(jié)果: 第1頁 第2頁 第3頁 第4頁
總結(jié):
前端要使用自定義過濾器,標簽和inclusion_tag都先要load.
在某個區(qū)域需要反復(fù)使用并且數(shù)據(jù)不固定,適合使用inclusion_tag.
13. 模板的導(dǎo)入
類似于python導(dǎo)模塊
例如有一個頁面會經(jīng)常用到,不可能每次用到就寫一份,可以使用模板導(dǎo)入的方法。
頁面導(dǎo)入模板關(guān)鍵字:{%include%}
經(jīng)常用到的頁面form.html
"en "> ta charset= "UTF-8 "> Title cript src= "https://cdn.bootcdn.net/ajax/libs/jquery/3.4.1/jquery.min.js "> cript> ink href= "https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/css/bootstrap.min.css " rel= "stylesheet "> cript src= "https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/js/bootstrap.min.js "> cript> "container
">
"row
">
"col-md-8 col-md-offset-2
">
模板導(dǎo)入:
需要用到模板的頁面: index.html {% include 'form.html ' %}
14. 模板的繼承
示例:
主頁home.html(模板)
"en "> ta charset= "UTF-8 "> Title cript src= "https://cdn.bootcdn.net/ajax/libs/jquery/3.4.1/jquery.min.js "> cript> ink href= "https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/css/bootstrap.min.css " rel= "stylesheet "> cript src= "https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/js/bootstrap.min.js "> cript> "container
">
"row
">
"navbar navbar-inverse "> "container-fluid
">
"navbar-header
">
"button " class= "navbar-toggle collapsed " data-toggle= "collapse " data-target= "#bs-example-navbar-collapse-1 " aria-expanded= "false "> "sr-only ">Toggle navigation "icon-bar "> "icon-bar "> "icon-bar "> "navbar-brand " href= "# ">Brand "collapse navbar-collapse
" id=
"bs-example-navbar-collapse-1
">
{% block co
ntent %}
{% endblock %}
電腦(compute.html)頁面繼承home.html
{% extends 'home.html ' %} {% block co ntent %} {% endblock %}
手機(phone.html)頁面繼承home.html
{% extends 'home.html ' %} {% block co ntent %} {% endblock %}
子模板不但能修改被標記的位置,還可以使用模板內(nèi)容:
{% extends 'home.html '%} {% block co ntent %} {{ block.super }} {% endblock %}
模板在標記區(qū)域的時候一般有三個區(qū)域
CSS區(qū)域 HTML區(qū)域 JS區(qū)域 目的是為了讓繼承的子模板具有獨立的CSS和JS,增加擴展性
{% balock css %} css 樣式 {% endblock %} {% balock html %} html內(nèi)容 {% endblock %} {% balock js %} js 內(nèi)容 {% endblock %} 子板也可以使用模板標記的區(qū)域的內(nèi)容: {{ block.super }}