先決條件: | 閱讀 Django簡介。 完成上一篇教程主題(包括 Django教程第4部分:Django管理網(wǎng)站)。 |
---|---|
目的: | 了解如何創(chuàng)建簡單的URL映射和視圖(在URL中沒有編碼數(shù)據(jù)),以及如何從模型獲取數(shù)據(jù)和創(chuàng)建模板。 |
現(xiàn)在我們已經(jīng)定義了我們的模型并創(chuàng)建了一些初始的庫記錄來處理,現(xiàn)在是編寫代碼以向用戶呈現(xiàn)信息的時(shí)候了。 我們需要做的第一件事是確定我們希望在我們的頁面中顯示哪些信息,然后定義返回這些資源的適當(dāng)?shù)腢RL。 然后,我們需要?jiǎng)?chuàng)建url映射器,視圖和模板來顯示這些頁面。
下面的圖提供了處理HTTP請求/響應(yīng)時(shí)需要實(shí)現(xiàn)的數(shù)據(jù)和事物的主要流程的提示。 由于我們已經(jīng)創(chuàng)建了模型,我們需要?jiǎng)?chuàng)建的主要內(nèi)容是:
正如你將在下一節(jié)中看到的,我們將有5個(gè)頁面來顯示,這在一篇文章中是很有用的。 因此,本文的大部分內(nèi)容將集中在展示如何實(shí)現(xiàn)主頁(我們將轉(zhuǎn)到后續(xù)文章中的其他頁面)。 這應(yīng)該讓您對URL映射器,視圖和模型在實(shí)踐中如何工作有良好的端到端理解。
由于此版本的LocalLibrary 對于最終用戶而言基本上是只讀的,因此我們只需為網(wǎng)站(首頁)和顯示列表的網(wǎng)頁提供著陸頁 和書和作者的詳細(xì)視圖。
我們需要為我們的網(wǎng)頁的網(wǎng)址是:
catalog/
—?The home/index page.catalog/books/
—?The list of all books.catalog/authors/
?— The list of all authors.catalog/book/<id>
?— The detail view for the specific?book with a field primary key of <id>
(the default). So?for example, /catalog/book/3
, for the third book added.catalog/author/<id>
?—?The detail view for the specific author?with a primary key field named?<id>.?
So for example, /catalog/author/11
, for the 11th author?added.前三個(gè)URL用于列出索引,書籍和作者。 這些不會編碼任何附加信息,并且盡管返回的結(jié)果將取決于數(shù)據(jù)庫中的內(nèi)容,運(yùn)行以獲取信息的查詢將始終相同。
相反,最后兩個(gè)URL用于顯示關(guān)于特定書或作者的詳細(xì)信息 - 這些URL編碼要在URL中顯示的項(xiàng)的標(biāo)識(示為 < id>
代碼>)。 URL映射器可以提取編碼信息并將其傳遞給視圖,然后它將動態(tài)確定從數(shù)據(jù)庫獲取什么信息。 通過在我們的URL中編碼信息,我們只需要一個(gè)url映射,視圖和模板來處理每本書(或作者)。
注意:Django允許您以任何方式構(gòu)建網(wǎng)址 - 您可以按上面所示對網(wǎng)址正文中的信息進(jìn)行編碼,或使用URL GET
參數(shù)(例如 > / book /?id = 6
)。 無論您使用哪種方法,網(wǎng)址都應(yīng)保持干凈,邏輯和可讀(此處查看W3C建議 / a>)。
Django文檔傾向于在URL的正文中推薦編碼信息,這是他們認(rèn)為鼓勵(lì)更好的URL設(shè)計(jì)的做法。
如概述中所討論的,本文的其余部分描述如何構(gòu)建索引頁。
我們將創(chuàng)建的第一個(gè)頁面是索引頁面( catalog /
)。 這將顯示一些靜態(tài)HTML,以及數(shù)據(jù)庫中不同記錄的一些計(jì)算的"計(jì)數(shù)"。 為了完成這項(xiàng)工作,我們必須創(chuàng)建一個(gè)URL映射,視圖和模板。
注意:在本節(jié)中值得特別注意。 一些材料是所有頁面的共同。
當(dāng)我們創(chuàng)建骨架網(wǎng)站時(shí),我們?yōu)槟夸洃?yīng)用程序創(chuàng)建了一個(gè)基本的 /catalog/urls.py 文件。 目錄應(yīng)用程序URL包含在映射 catalog /
的項(xiàng)目中,因此獲取到此映射器的URL必須以 catalog /
開頭 在正斜杠之后的URL中的所有字符串)。
打開 urls.py ,然后粘貼下面粗體顯示的行。
urlpatterns = [ url(r'^$', views.index, name='index'), ]
這個(gè) url()
函數(shù)定義了一個(gè)URL模式( r\'^ $\'
)和一個(gè)視圖函數(shù),如果檢測到模式 index - views.py 中名為 index()
的函數(shù)。 網(wǎng)址格式是 Python正則表達(dá)式(RE)。 我們將在本教程中進(jìn)一步討論RE,但對于這種情況,所有你需要知道的是,^ $的RE將模式匹配空字符串(^是字符串開始標(biāo)記,$是結(jié)束 的字符串標(biāo)記)。
注意:匹配的網(wǎng)址實(shí)際上是 catalog /
+< empty string> (因?yàn)槲覀冊?strong>目錄應(yīng)用程序中,假定為 / catalog /
)。 如果我們收到一個(gè)URL為 / catalog /
的HTTP請求,我們的第一個(gè)視圖函數(shù)將被調(diào)用。
此 url()
函數(shù)還指定了 name
參數(shù),該參數(shù)唯一標(biāo)識了此特定的URL映射。 您可以使用此名稱"反轉(zhuǎn)"映射器 - 動態(tài)創(chuàng)建指向映射器設(shè)計(jì)處理的資源的URL。 例如,現(xiàn)在我們可以通過在我們的模板中創(chuàng)建以下鏈接來鏈接到我們的主頁:
<a href="{% url 'index' %}">Home</a>.
注意:我們當(dāng)然可以對上述鏈接進(jìn)行硬編碼(例如< a href =" / catalog / "> Home< / a>
>),但是如果我們改變主頁的模式(例如到 / catalog / index
),模板將不再正確鏈接。 使用反向url映射是更加靈活和健壯!
視圖是一種處理HTTP請求,根據(jù)需要從數(shù)據(jù)庫獲取數(shù)據(jù),通過使用HTML模板呈現(xiàn)此數(shù)據(jù)來生成HTML頁面,然后在HTTP響應(yīng)中返回HTML以向用戶顯示的功能。 索引視圖遵循此模型 - 它獲取有關(guān)多少 Book
, BookInstance
,可用的 BookInstance
和 Author
記錄 我們在數(shù)據(jù)庫中,并將它們傳遞到模板進(jìn)行顯示。
打開 catalog / views.py ,并注意該文件已導(dǎo)入 shortcuts.render"class ="external"> render()快捷方式函數(shù),使用模板和數(shù)據(jù)生成HTML文件。
from django.shortcuts import render # Create your views here.
復(fù)制文件底部的以下代碼。 第一行導(dǎo)入我們將在所有視圖中訪問的模型類。
from .models import Book, Author, BookInstance, Genre def index(request): """ View function for home page of site. """ # Generate counts of some of the main objects num_books=Book.objects.all().count() num_instances=BookInstance.objects.all().count() # Available books (status = 'a') num_instances_available=BookInstance.objects.filter(status__exact='a').count() num_authors=Author.objects.count() # The 'all()' is implied by default. # Render the HTML template index.html with the data in the context variable return render( request, 'index.html', context={'num_books':num_books,'num_instances':num_instances,'num_instances_available':num_instances_available,'num_authors':num_authors}, )
視圖函數(shù)的第一部分使用模型類上的 objects.all()
屬性獲取記錄計(jì)數(shù)。 它還獲取一個(gè)狀態(tài)字段值為\'a\'(可用)的 BookInstance
對象的列表。 您可以在上一篇教程中了解有關(guān)如何從模型訪問的更多信息( Django教程第3部分:使用模型>搜索記錄) )。
在函數(shù)結(jié)束時(shí),我們調(diào)用 render()
函數(shù)創(chuàng)建并返回一個(gè)HTML頁面作為響應(yīng)(這個(gè)快捷函數(shù)包裝了許多其他函數(shù),簡化了這個(gè)常見的用例)。 這采用原始的 request
對象(一個(gè) HttpRequest
),一個(gè)具有數(shù)據(jù)占位符的HTML模板和一個(gè) context
包含將插入到這些占位符中的數(shù)據(jù)的字典)。
我們將在下一節(jié)中更多地討論模板和上下文變量; 讓我們創(chuàng)建我們的模板,這樣我們可以向用戶顯示一些東西!
模板是定義文件(例如HTML頁面)的結(jié)構(gòu)或布局的文本文件,具有用于表示實(shí)際內(nèi)容的占位符。 Django會自動在應(yīng)用程序中名為"模板"的目錄中查找模板。 因此,例如,在我們剛才添加的索引視圖中, render()
函數(shù)將期望能夠找到 / locallibrary / catalog / templates / 127.0.0.1:8000
現(xiàn)在將提供一個(gè)相當(dāng)直觀的錯(cuò)誤消息"TemplateDoesNotExist at / catalog /", 。
注意:根據(jù)項(xiàng)目的設(shè)置文件,Django會查看多個(gè)模板的位置(在已安裝的應(yīng)用程序中搜索是默認(rèn)設(shè)置!)。 您可以在模板中找到更多關(guān)于Django如何查找模板及其支持的模板格式的信息。 a>(Django docs)。
注意:根據(jù)項(xiàng)目的設(shè)置文件,Django會查看多個(gè)模板的位置(在已安裝的應(yīng)用程序中搜索是默認(rèn)設(shè)置!)。 您可以在模板中找到更多關(guān)于Django如何查找模板及其支持的模板格式的信息。 a>(Django docs)。...
例如,基本模板 base_generic.html 可能類似于以下文本。 如您所見,這包含一些"常見的"HTML和標(biāo)題,邊欄和使用命名的 block
和 endblock
模板標(biāo)簽(以粗體顯示)標(biāo)記的內(nèi)容的部分。 塊可以為空,或包含將為"派生頁"默認(rèn)使用的內(nèi)容。
注意:模板標(biāo)簽就像可以在模板中使用的函數(shù),用于循環(huán)遍歷列表,基于變量的值執(zhí)行條件操作等。除了模板 標(biāo)記模板語法允許您引用模板變量(從視圖傳遞到模板中),并使用重新格式化變量(例如,將字符串設(shè)置為小寫)的模板過濾器。
<!DOCTYPE html> <html lang="en"> <head> {% block title %}<title>Local Library</title>{% endblock %} </head> <body> {% block sidebar %}<!-- insert default navigation text for every page -->{% endblock %} {% block content %}<!-- default content text (typically empty) -->{% endblock %} </body> </html>
當(dāng)我們想為特定視圖定義一個(gè)模板時(shí),我們首先指定基本模板(使用 extend
模板標(biāo)簽 - 參見下一個(gè)代碼清單)。 如果在模板中有要替換的任何部分,我們使用與基本模板中使用的相同的 block
/ endblock
部分聲明這些部分。
例如,下面的代碼片段顯示了我們?nèi)绾问褂?code> extends 模板標(biāo)記,并覆蓋 content
塊。 最終生成的HTML將包含基本模板中定義的所有HTML和結(jié)構(gòu)(包括您在 title
塊中定義的默認(rèn)內(nèi)容),但使用新的內(nèi)容
塊插入代替detault一。
{% extends "base_generic.html" %} {% block content %} <h1>Local Library Home</h1> <p>Welcome to <em>LocalLibrary</em>, a very basic Django website developed as a tutorial example on the Mozilla Developer Network.</p> {% endblock %}
我們計(jì)劃用于 LocalLibrary 網(wǎng)站的基本模板如下所示。 如您所見,這包含了 title
, sidebar
和 content
的一些HTML和定義的塊。 我們有一個(gè)默認(rèn)標(biāo)題(我們可能想要更改)和一個(gè)默認(rèn)邊欄,其中包含所有圖書和作者的列表鏈接(我們可能不想更改,但我們允許范圍這樣做,如果需要, 在塊中)。
注意:我們還引入了兩個(gè)其他模板標(biāo)簽: url
和 load static
。 這些將在以下各節(jié)中討論。
創(chuàng)建新文件 - / locallibrary / catalog / templates / base_generic.html - 并提供以下內(nèi)容:
<!DOCTYPE html> <html lang="en"> <head> {% block title %}<title>Local Library</title>{% endblock %} <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="stylesheet" rel="external nofollow" target="_blank" > <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js" rel="external nofollow" ></script> <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" rel="external nofollow" ></script> <!-- Add additional CSS in static file --> {% load static %} <link rel="stylesheet" href="{% static 'css/styles.css' %}"> </head> <body> <div class="container-fluid"> <div class="row"> <div class="col-sm-2"> {% block sidebar %} <ul class="sidebar-nav"> <li><a href="{% url 'index' %}">Home</a></li> <li><a href="">All books</a></li> <li><a href="">All authors</a></li> </ul> {% endblock %} </div> <div class="col-sm-10 "> {% block content %}{% endblock %} </div> </div> </div> </body> </html>
該模板使用(并包括)來自 Bootstrap 的JavaScript和CSS,以改進(jìn)HTML頁面的布局和顯示方式。 使用Bootstrap或另一個(gè)客戶端web框架是一個(gè)快速的方法來創(chuàng)建一個(gè)有吸引力的網(wǎng)頁,可以擴(kuò)大在不同的瀏覽器大小,它也允許我們處理頁面演示,而無需進(jìn)入任何細(xì)節(jié) - 我們只是 想在這里聚焦于服務(wù)器端代碼!
基本模板還引用了一個(gè)提供一些額外樣式的本地css文件( styles.css )。 創(chuàng)建 /locallibrary/catalog/static/css/styles.css 并提供以下內(nèi)容:
.sidebar-nav { margin-top: 20px; padding: 0; list-style: none; }
創(chuàng)建HTML文件 / locallibrary / catalog / templates / index.html ,并為其提供如下所示的內(nèi)容。 您可以看到,我們在第一行中擴(kuò)展了我們的基本模板,然后將默認(rèn)的 content
塊替換為此模板的新模塊。
{% extends "base_generic.html" %} {% block content %} <h1>Local Library Home</h1> <p>Welcome to <em>LocalLibrary</em>, a very basic Django website developed as a tutorial example on the Mozilla Developer Network.</p> <h2>Dynamic content</h2> <p>The library has the following record counts:</p> <ul> <li><strong>Books:</strong> {{ num_books }}</li> <li><strong>Copies:</strong> {{ num_instances }}</li> <li><strong>Copies available:</strong> {{ num_instances_available }}</li> <li><strong>Authors:</strong> {{ num_authors }}</li> </ul> {% endblock %}
在動態(tài)內(nèi)容部分中,我們?yōu)橐晥D中包含的信息聲明了占位符(模板變量)。 變量使用"雙括號"或"句柄"語法標(biāo)記(參見上面的粗體部分)。
注意:您可以輕松地識別是否要使用模板變量或模板標(biāo)簽(函數(shù)),因?yàn)樽兞烤哂须p括號( {{num_books}}
),而代碼 ( {%extends"base_generic.html"%}
)的單個(gè)大括號中。
這里需要注意的是,這些變量是用我們傳遞給 context
字典的鍵命名的。 (見下文); 當(dāng)呈現(xiàn)模板時(shí),這些將被其相關(guān)聯(lián)的值替換。
return render( request, 'index.html', context={'num_books':num_books,'num_instances':num_instances,'num_instances_available':num_instances_available,'num_authors':num_authors}, )
您的項(xiàng)目可能使用靜態(tài)資源,包括JavaScript,CSS和圖像。 由于這些文件的位置可能未知(或可能會更改),因此Django允許您在模板中相對于 STATIC_URL
全局設(shè)置指定這些文件的位置(默認(rèn)框架網(wǎng)站設(shè)置值 STATIC_URL
改為\' / static /
\',但您可以選擇在內(nèi)容傳送網(wǎng)絡(luò)或其他地方托管這些內(nèi)容。
在模板中,您首先調(diào)用l oad
模板標(biāo)簽,指定"static"以添加此模板庫(如下所示)。 加載靜態(tài)后,您可以使用 static
模板標(biāo)記,指定相關(guān)文件的相對URL。
<!-- Add additional CSS in static file --> {% load static %} <link rel="stylesheet" href="{% static 'css/styles.css' %}">
如果需要,可以以相同的方式在頁面中添加圖像。 例如:
{% load static %} <img src="{% static 'catalog/images/local_library_model_uml.png' %}" style="width:555px;height:540px;"/>
注意:上面的更改指定了文件的位置,但Django不會默認(rèn)提供這些文件。 雖然當(dāng)我們創(chuàng)建網(wǎng)站骨架時(shí),我們已啟用全球網(wǎng)址映射程序( /locallibrary/locallibrary/urls.py )中的開發(fā)網(wǎng)絡(luò)服務(wù)器 ,您仍然需要安排他們在生產(chǎn)中服務(wù)。 我們稍后會看這個(gè)。
有關(guān)使用靜態(tài)文件的詳細(xì)信息,請參閱管理靜態(tài)文件(Django docs)。
上面的基本模板引入了 url
模板標(biāo)記。
<li><a href="{% url 'index' %}">Home</a></li>
此標(biāo)記采用 urls.py 中調(diào)用的 url()
函數(shù)的名稱,以及關(guān)聯(lián)視圖從該函數(shù)接收的任何參數(shù)的值,并返回一個(gè)網(wǎng)址 您可以使用鏈接到資源。
在這一點(diǎn)上,我們應(yīng)該創(chuàng)建顯示索引頁所需的一切。 運(yùn)行服務(wù)器( python3 manage.py runserver
),然后打開瀏覽器 http://127.0。 0.1:8000 / 。 如果一切設(shè)置正確,您的網(wǎng)站應(yīng)該看起來像下面的屏幕截圖。
; width:874px;">
注意:您將無法使用所有圖書和所有作者鏈接,因?yàn)檫@些鏈接的網(wǎng)址,視圖和模板 網(wǎng)頁尚未定義(目前我們只是在 base_generic.html
模板中為這些鏈接插入了占位符)。
這里有幾個(gè)任務(wù)來測試你對模型查詢,視圖和模板的熟悉程度。
我們現(xiàn)在已經(jīng)為我們的網(wǎng)站創(chuàng)建了一個(gè)主頁 - 一個(gè)HTML頁面,其中顯示了數(shù)據(jù)庫中的一些記錄數(shù)量,并且鏈接到我們的其他待創(chuàng)建頁面。 一路上,我們學(xué)到了很多關(guān)于URL映射器,視圖,使用我們的模型查詢數(shù)據(jù)庫,如何從視圖傳遞信息到模板以及如何創(chuàng)建和擴(kuò)展模板的基本信息。
在下一篇文章中,我們將基于我們的知識創(chuàng)建其他四個(gè)頁面。
更多建議: