Django 2.0 學習(13):Django模板繼承和靜態文件


Django模板繼承和靜態文件

模板繼承(extend)

Django模板引擎中最強大也是最復雜的部分就是模板繼承了,模板繼承可以讓我們創建一個基本的"骨架"模板,它可以包含網頁中的全部元素,並且可以定義能夠被子模板覆蓋的blocks。為了容易理解模板繼承,我們先寫一個模板:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>{% block title %}Replaceable template{% 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骨架。"子模板"可以用它們的內容填充空白的blocks。在這個例子中,block標簽定義了三個可以被子模板內容填充的block,block告訴模板引擎:子模板可能會覆蓋掉模板中的這些位置。

接下來,我們再寫一個子模板:

{% extends "polls/base.html" %}        # 模板路徑根據項目或者app的路徑來寫,筆者這里的模板位於app中

{% block title %}Child template{% endblock %}

{% block content %}
    {% for entry in blog_entries %}
        <h3>{{ entry.title }}</h3>
        <p>{{ entry.body }}</p>
    {% endfor %}
{% endblock %}

extends標簽是這里的關鍵,它告訴模板引擎這個模板繼承了另一個模板。當模板系統處理這個模板時,首先定位父模板--此例中,就是"base.html"。那時模板引擎注意到base.html中的三個block標簽,並用子模板中的內容來替換這些block。根據blog_entries的值,子模板輸出的內容會是下面的內容:

<!DOCTYPE html>
<html lang="en">
<head>
    <link rel="stylesheet" href="style.css" />
    <title>Child template</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,所以系統使用了父模板中的值。父模板的{% block %}標簽中的內容總是被用作備選內容。這種方式使代碼得到最大程度的復用,並且使得添加內容到共享的內容區域更加簡單,例如:部分范圍內的導航。

說明:

1.如果在模板中使用{% extends %}標簽,它必須是模板中的第一個標簽,其他的任何情況下,模板繼承都將無法工作;
2.在base模版中設置越多的 {% block %} 標簽越好。請記住,子模版不必定義全部父模版中的block,所以,我們可以在大多數>block中填充合理的默認內容,然后,只定義我們需要的那一個。多一點鈎子總比少一點好;
3.如果發現我們在大量的模板中復制內容,那就意味着我們應該把內容移動到父模板中的一個{% block %}中;
4.有時候,想在父模板的基礎上再添加點其他的,而不是完全覆蓋父模板的內容,那么我們只需要在想要填充的塊里,再加上 >{{ block.super }}語句,我們就可以把父模板里的東西給留下來,如:

父模板中的
{% block title %}Parent template{% endblock %}

如果我們只想子模板的結果是在后面添加一個!,則只需要在子模板中寫成
{% block title %}
    {{ block.super }}!
{% endblock %}

5.為了更好的可讀性,也可以給我們的 {% endblock %} 標簽一個 名字 。例如:

{% block content %}
...
{% endblock content %} 

6.在大型模板中,這個方法可以幫助我們清楚的看到哪個 {% block %}標簽被關閉了;

最后,請注意我們不能在一個模版中定義多個相同名字的 block 標簽。這個限制的存在是因為block標簽的作用是“雙向”的。這個意思是,block標簽不僅提供了一個坑去填,它還在父模版中定義了填坑的內容。如果在一個模版中有兩個名字一樣的 block 標簽,子模版的父模版將不知道使用哪個block的內容。

注意:模板一般放在app下的templates中,Django會自動去這個文件夾中找。但 假如我們每個app的templates中都有一個 index.html,當我們在views.py中使用的時候,直接寫一個 render(request, 'index.html'),Django 能不能找到當前 app 的 templates 文件夾中的 index.html 文件夾呢?(答案是不一定能,有可能找錯)

Django模板查找機制:Django 查找模板的過程是在每個 app 的 templates 文件夾中找(而不只是當前 app 中的代碼,只在當前 app 的 templates 文件夾中找)。各個 app 的 templates 形成一個文件夾列表,Django 遍歷這個列表,一個個文件夾進行查找,當在某一個文件夾找到的時候就停止,所有的都遍歷完了還找不到指定的模板的時候就是 Template Not Found (過程類似於Python找包)。這樣設計有利當然也有弊,有利是的地方是一個app可以用另一個app的模板文件,弊是有可能會找錯了。所以我們使用的時候在 templates 中建立一個 app 同名的文件夾,這樣就好了。這就需要把每個app中的 templates 文件夾中再建一個 app 的名稱,僅和該app相關的模板放在 app/templates/app/ 目錄下面。這樣在使用的時候,有app作為名稱的一部分,就不會混淆。

模板include

假如我們有以下模板index.html,代碼:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<div>網頁公共頭部部分</div>

<h2> 網頁body部分 </h2>

<div>網頁公共底部部分</div>

</body>
</html>

做過web開發的同學都知道大部分網頁的公共頭部,公共底部部分代碼每個頁面都一樣,那么就應該將其單獨拿出做為一個html, 這樣修改這部分代碼時候,不需要每個頁面都修改, 所以在django中我們可以這么做:
top.html

<div>網頁公共頭部部分</div>

bottom.html

<div>網頁公共底部部分</div>

index.html

<!DOCTYPE html>  
<html lang="en">  
<head>  
    <meta charset="UTF-8">  
    <title>Title</title>  
</head>  
<body>  
  
{% include 'top.html' %}  
  
<h2> 網頁body部分 </h2>  
  
{% include 'bottom.html' %}  
  
</body>  
</html>

我們可以使用Django模板引擎的include語法,來將單獨的頁面包含到當前模板頁面中。有同學有疑問,那我們通過視圖傳遞給模板的上下文,在被包含的模板中可以使用嗎?可以直接使用,假如我們的視圖函數如下:

def index(request):  
    return render(request, 'polls/index.html', {'a': 100, 'b': 200})

該Django視圖函數,傳遞給模板並渲染模板。

top.html修改如下:

<div>網頁公共頭部部分:{{ a }}</div>      # 這樣使用沒有任何問題

我這里有這樣的一個問題,假如所有的頁面都使用共同的頭部top.html, 可能針對1.html 2.html 3.html所使用的頭部有些樣式不一樣,所需top.html:

<div classs='acss'>網頁公共頭部部分</div>  

但是對於5.html, 6.html使用的頭部樣式為:

<div class='bcss'>網頁公共頭部部分</div>  

很顯然,如果直接通過include方式包含公共頭部,會導致一些頁面顯示問題。既然部分參數不一樣,include允許我們傳遞參數給被include的模板,我們可以使用with語法,那么問題解決如下:

{{ % include 'top.html' with mycss='acss' % }}  

top.html修改如下:

<div class='{{mycss}}'>網頁公共頭部部分</div> 

被包含模板中部分參數,由我們include的時候動態指定,那么top.html就不會因為細微差別而編寫多份代碼了。

靜態文件配置

我們自己導入的一些頁面相關的包就叫做靜態文件

  • 在app目錄中先創建static目錄;
  • 在static目錄里面導入我們的JS、CSS、Jquery和Bootstrap等;
  • 在項目settings.py中添加一些配置;
STATIC_URL = '/static/'   #這個配置就相當於下面配置的別名,如果這里的名字修改了就按照這里的名字去導入
STATICFILES_DIRS = [
    os.path.join(BASE_DIR,"static")  #E:\day68\static 找到static路徑
]
  • 導入網頁相關圖片、CSS、JS、Jquery等
<link rel = "stysheet",href= "/static/index.css/"> 

<link rel="stylesheet" href="/static/bootstrap-3.3.7-dist/css/bootstrap.min.css">


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM