Django-模板語法

官方文檔css

 

引言

你可能已經注意到咱們在例子視圖中返回文本的方式有點特別。 也就是說,HTML被直接硬編碼在 Python代碼之中html

 

def current_datetime(request):
    now = datetime.datetime.now()
    html = "<html><body>It is now %s.</body></html>" % now
    return HttpResponse(html)

儘管這種技術便於解釋視圖是如何工做的,但直接將HTML硬編碼到你的視圖裏卻並非一個好主意。 讓咱們來看一下爲何:前端

  • 對頁面設計進行的任何改變都必須對 Python 代碼進行相應的修改。 站點設計的修改每每比底層 Python 代碼的修改要頻繁得多,所以若是能夠在不進行 Python 代碼修改的狀況下變動設計,那將會方便得多。python

  • Python 代碼編寫和 HTML 設計是兩項不一樣的工做,大多數專業的網站開發環境都將他們分配給不一樣的人員(甚至不一樣部門)來完成。 設計者和HTML/CSS的編碼人員不該該被要求去編輯Python的代碼來完成他們的工做。程序員

  • 程序員編寫 Python代碼和設計人員製做模板兩項工做同時進行的效率是最高的,遠勝於讓一我的等待另外一我的完成對某個既包含 Python又包含 HTML 的文件的編輯工做。npm

基於這些緣由,將頁面的設計和Python的代碼分離開會更乾淨簡潔更容易維護。 咱們可使用 Django的 模板系統 (Template System)來實現這種模式,這就是本章要具體討論的問題。django

 一:模板的介紹

1:什麼是模板

只要是在html裏面有模板語法就不是html文件了,這樣的文件就叫作模板。bootstrap

官方文檔的定義:後端

模板就是一個簡單的文本文件,它能夠生成任何文本格式(HTML,XML,CSV等)。瀏覽器

模板中包含變量和標籤,當模板被執行時,變量會被賦值,而標籤是控制模板的邏輯的。

2:模板語法的分類

(1)變量:{{}}  {{ 變量名 }}

(2)標籤:{% %}   {% tag %}.

3:模板語法的渲染方式

模板語法由render()渲染的.

瀏覽器接收到的數據是已經通過渲染以後的數據

二:模板語法的介紹

1:變量介紹

變量看起來像這樣:{{ 變量名 }},當模板引擎遇到變量時,會計算這個變量,並把結果賦值給它。變量名是由任何的數字,字母以及下劃線組成。點(「.」)也會出如今變量部分,固然他有特殊用途,稍後會說明。特別注意的是,變量名中不能出現空格符以及任何的標點符號。

上面說到點也會出如今變量部分,它的做用就是用來訪問變量的屬性的。

2:變量(渲染變量)

(1) 變量渲染各類類型

1 <body>
2     <p>變量渲染各類數據類型</p>
3     <ul>
4         <li>name:{{ name }}</li>
5         <li>age:{{ age }}</li>
6         <li>student{{ student }}</li>
7     </ul>
8 </body>
index.html
1 def index(request):
2     name = 'lilz'   #str
3     age = 20        #int
4     student=['egon','wusir','yaoshen']  #list
5     return render(request,'index.html',{'name':name,'age':age,'student':student})
views.py

測試:

 

(2)深度查詢

使用句點符(.)一層一層往裏層查詢

仍是上面的案例:文件不作修改,只更改index.html中的

<li>student:{{ student.0 }}</li>

那麼測試結果

(3)locals

那麼若是須要傳的很是多的參數時,locals代替傳變量的參數

    name = 'lilz'   #str
    age = 20        #int
    student=['egon','wusir','yaoshen']  #list
    return render(request,'index.html',{'name':name,'age':age,'student':student})
    return render(request,'index.html',locals())  #效果和上面的相同

(4)filter過濾器--內置

做用:
  過濾器轉換變量和標記參數的值。簡言之,把原本的數據在根據規則過濾一遍。
語法
  {{var|filter_name:參數}} ---{{變量|過濾器名:參數}}

請參考博客:Django-模板語法-過濾器



3:標籤(渲染標籤)

標籤看起來像是這樣的: {% tag %}。標籤比變量更加複雜:一些在輸出中建立文本,一些經過循環或邏輯來控制流程,一些加載其後的變量將使用到的額外信息到模版中。一些標籤須要開始和結束標籤 (例如{% tag %} ...標籤 內容 ... {% endtag %})

 

請參考博文:Django-模板語法-標籤

 

 三:模板繼承

1:引言

 

2:介紹

 Django模版引擎中最強大也是最複雜的部分就是模版繼承了。模版繼承可讓您建立一個基本的「骨架」模版,它包含您站點中的所有元素,而且能夠定義可以被子模版覆蓋的 blocks 。

 

3:案例

咱們下面的計劃是作一個母版,讓其餘子模板頁面可以繼承母版

(1)母版文件

 1 <!DOCTYPE html>
 2 <html lang="en">
 3 <head>
 4     <meta charset="UTF-8">
 5     <title>Title</title>
 6     <!-- 最新版本的 Bootstrap 核心 CSS 文件 -->
 7     <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css"
 8           integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
 9     <style>
10         * {
11             padding: 0;
12             margin: 0;
13         }
14 
15         .header {
16             width: 100%;
17             height: 50px;
18             background-color: #369;
19         }
20     </style>
21 </head>
22 <body>
23 <div class="header"></div>
24 <div class="container">
25     <div class="row">
26         <div class="col-md-3">
27             <div class="panel panel-success">
28                 <div class="panel-body">
29 
30                 </div>
31                 <div class="panel-footer">
32                     <p><a href="/app01/order/">訂單</a></p>
33                     <p><a href="">商品信息</a></p>
34                     <p><a href="">價格</a></p>
35                     <p><a href="">走勢</a></p>
36                 </div>
37             </div>
38         </div>
39         <div class="col-md-9">
40 
41             <div class="">
42                 {% block content %}
43                     <h3>welcome !</h3>
44                 {% endblock %}
45             </div>
46         </div>
47 
48     </div>
49 </div>
50 </body>
51 </html>
base.html

 

(2)子模板文件

1 {% extends 'base.html' %}
2 
3 {% block content %}
4     <div class="jumbotron">
5         <h1>Hello, world!</h1>
6         <p>...</p>
7         <p><a class="btn btn-primary btn-lg" href="#" role="button">Learn more</a></p>
8     </div>
9 {% endblock %}
index.html
1 {% extends 'base.html' %}
2 
3 {% block content %}
4     <h3>這是訂單</h3>
5 {% endblock %}
order.html

 

 (3)py文件

 1 from django.contrib import admin
 2 from django.urls import path,re_path,include
 3 from app01 import views
 4 
 5 
 6 urlpatterns = [
 7 
 8     re_path(r'index/$',views.index),
 9     re_path(r'order/$',views.order),
10 ]
app01/urls.py
1 from django.shortcuts import render,HttpResponse
2 
3 def index(request):
4 
5     return render(request,'index.html')
6 
7 def order(request):
8 
9     return render(request,'order.html')
views.py

 

測試

而後咱們點擊訂單,就會跳到下面頁面

 

總結

 

extends 標籤是這裏的關鍵。它告訴模版引擎,這個模版「繼承」了另外一個模版。當模版系統處理這個模版時,首先,它將定位父模版——在此例中,就是「base.html」。

那時,模版引擎將注意到 base.html 中的 block 標籤,並用子模版中的內容來替換這些block。


 

注意:

  • 若是你在模版中使用 {% extends %} 標籤,它必須是模版中的第一個標籤。其餘的任何狀況下,模版繼承都將沒法工做。

  • 在base模版中設置越多的 {% block %} 標籤越好。請記住,子模版沒必要定義所有父模版中的blocks,因此,你能夠在大多數blocks中填充合理的默認內容,而後,只定義你須要的那一個。多一點鉤子(block)總比少一點好。

  • 若是你發現你本身在大量的模版中複製內容,那可能意味着你應該把內容移動到父模版中的一個 {% block %} 中。

  • If you need to get the content of the block from the parent template, the {{ block.super }} variable will do the trick. This is useful if you want to add to the contents of a parent block instead of completely overriding it. Data inserted using {{ block.super }} will not be automatically escaped (see the next section), since it was already escaped, if necessary, in the parent template.

    • 在母版中的一個block裏面的內容,當子模板繼承的時候就會覆蓋母版的這個block裏面的內容。那麼咱們既想要這個內容還想要子母版的內容,該怎麼辦呢?
    • 方法就是在子模板繼承的時候添加一個{{ block.super }}
  • 爲了更好的可讀性,你也能夠給你的 {% endblock %} 標籤一個 名字 。例如:

    1
    2
    3
    { %  block content  % }
    ...
    { %  endblock content  % }  

    在大型模版中,這個方法幫你清楚的看到哪個  {% block %} 標籤被關閉了。

  • 不能在一個模版中定義多個相同名字的 block 標籤。

 

4:模板繼承的補充--include

母版繼承一個子模板文件

 

(1)母版

<body>
<h3>編輯書籍</h3>
<div class="container">
    <div class="row">
        <div class="col-md-6 col-md-offset-3"> {% include 'form.html' %} </div>
    </div>
</div>
</body>

 

(2)子模板form.html(所有數據)(不作任何處理)

<form action="" method="post" novalidate>
    {% csrf_token %}
      {% for field in form %}
        <div class="form-group">
             <label for="title">{{ field.label }}</label>
             {{ field }}
             <span>{{ field.errors.0 }}</span>
        </div>
     {% endfor %}
    <input type="submit" value="提交" class="btn btn-default pull-right">
</form>

 

 

這樣的效果就是母版把子模板數據加入到本身相應的位置

 

5:模板繼承的補充--include--優化-inclusion_tag

5.1缺點

咱們先說下上面的子模板的缺點:

子模板中的數據有視圖提供,可是這是有問題的,若是同時有其餘文件繼承母版,那麼若是對應的視圖函數就必須得提供數據才行。這樣太麻煩,數據和模板脫離開了。

{% include 'form.html' %}  #這個include是簡單地,只須要把form.html文件中的內容拿過來放到該位置就好了

 

5.2解決數據和模板脫離的方法--自定義標籤

 步驟和自定義過濾器同樣:博客

5.2.1 自定義標籤文件--提供數據

from django.template import Library

register = Library()

@register.inclusion_tag("includ.html")
def get_menu_style():

    menu_list=[123,666,999]
    return {"menu_list":menu_list}

 

 

5.2.2子模板文件--加工數據與模板語法的中轉站

includ.html

<ul>
    {% for foo in menu_list %}
        <li>{{ foo }}</li>
    {% endfor %}
</ul>

 

 

5.2.3母版文件---調用

 layout.html

                {% load myfilters_tags %}  #加載標籤文件
                {% get_menu_style %}  #模板語法

  

 四:render方法的做用

 

其實咱們寫的模板語法與瀏覽器一點關係都沒有。這其實都是後端解析數據,就是在render這個地方。其實render會把對應的模板文件讀出來。所有當作字符串。在字符串裏找到模板語法,把視圖函數中數據替換到相應位置。而後替換爲前端代碼

 

 


 

參考博文:Yuan 先生

相關文章
相關標籤/搜索