|
我們現(xiàn)在可以添加代碼來顯示我們的第一個(gè)完整頁(yè)面 - LocalLibrary 網(wǎng)站的主頁(yè),顯示每個(gè)模型類型有多少條記錄,并提供我們其他頁(yè)面的側(cè)邊欄導(dǎo)航鏈接。一路上,我們將獲得編寫基本URL地圖和視圖,從數(shù)據(jù)庫(kù)獲取記錄以及使用模板的實(shí)踐經(jīng)驗(yàn)。 現(xiàn)在我們已經(jīng)定義了我們的模型,并創(chuàng)建了一些初始庫(kù)記錄來處理,現(xiàn)在是編寫代碼以向用戶呈現(xiàn)該信息的時(shí)候了。我們需要做的第一件事是確定我們希望能夠在我們的頁(yè)面中顯示哪些信息,然后為返回這些資源定義適當(dāng)?shù)腢RL。那么我們將需要?jiǎng)?chuàng)建一個(gè)url映射器,視圖和模板來顯示這些頁(yè)面。 以下圖表提供了處理HTTP請(qǐng)求/響應(yīng)時(shí)需要實(shí)現(xiàn)的數(shù)據(jù)和事情的主要流程。我們已經(jīng)創(chuàng)建了這個(gè)模型,我們需要?jiǎng)?chuàng)建的主要內(nèi)容是: URL映射-根據(jù)-支持的URL(以及任何編碼在URL里的信息)跳轉(zhuǎn)到相應(yīng)的View功能函數(shù)。 View 函數(shù)從模型中獲取請(qǐng)求的數(shù)據(jù),創(chuàng)建一個(gè)顯示數(shù)據(jù)的HTML頁(yè)面,并將其返回給用戶在瀏覽器查看。 Templates 在View視圖中進(jìn)行數(shù)據(jù)渲染的時(shí)候使用。

正如你將在下一節(jié)中看到的,我們將要顯示5個(gè)頁(yè)面,這在一篇文章中是很重要的。因此,本文的大部分內(nèi)容將重點(diǎn)介紹如何實(shí)現(xiàn)主頁(yè)(我們將在隨后的文章中介紹其他頁(yè)面)。這應(yīng)該讓您對(duì)URL映射器,視圖和模型在實(shí)踐中如何工作有一個(gè)很好的端到端的了解。 由于本版本的LocalLibrary對(duì)于最終用戶本質(zhì)上是只讀的,所以我們只需要為該網(wǎng)站(主頁(yè))提供一個(gè)著陸頁(yè),以及顯示書籍和作者的列表和詳細(xì)視圖的頁(yè)面。 下面這些URL 是我們頁(yè)面需要的: catalog/ — 主頁(yè)
catalog/books/ — 書單頁(yè)
catalog/authors/ — 作者頁(yè)
catalog/book/<id> — 主鍵字段 ID的具體書(默認(rèn)) —詳細(xì)視圖。如下例子 /catalog/book/3,第三本書。
catalog/author/<id> — 主鍵字段 ID的具體作者(默認(rèn)) —詳細(xì)視圖。如下例子 /catalog/author/11,第11個(gè)作者。
前三個(gè)URL用于列出索引,書籍和作者。這些不會(huì)對(duì)任何附加信息進(jìn)行編碼,而返回的結(jié)果將取決于數(shù)據(jù)庫(kù)中的內(nèi)容,運(yùn)行獲取信息的查詢將始終保持一致。 相比之下,最后兩個(gè)URL用于顯示有關(guān)特定書籍或作者的詳細(xì)信息 - 這些URL將編碼要顯示在URL中的項(xiàng)目的標(biāo)識(shí)(如上所示<id>)。URL映射器可以提取編碼信息并將其傳遞給視圖,然后將動(dòng)態(tài)地確定從數(shù)據(jù)庫(kù)獲取哪些信息。通過對(duì)我們的URL中的信息進(jìn)行編碼,我們只需要一個(gè)URL映射,視圖和模板來處理每本書(或作者)。 注意:Django允許您以任何您喜歡的方式構(gòu)建您的URL - 您可以如上所示編碼URL正文中的信息,或使用URL GET參數(shù)(例如 /book/?id=6)。無論您使用哪種方法,URL都應(yīng)保持清潔,邏輯和可讀性 (check out the W3C advice here).
Django文檔傾向于在URL的主體中推薦編碼信息,這是他們覺得鼓勵(lì)更好的URL設(shè)計(jì)的實(shí)踐。 如概述,本文其余部分介紹如何構(gòu)建索引頁(yè) 創(chuàng)建索引頁(yè)節(jié)我們創(chuàng)建的第一個(gè)頁(yè)面將會(huì)是索引頁(yè)(catalog/)。這會(huì)顯示一些靜態(tài)HTML,以及數(shù)據(jù)庫(kù)中不同記錄的一些計(jì)算的“計(jì)數(shù)“。為了使其工作,我們必須創(chuàng)建一個(gè)URL映射,視圖和模版。 注意: 本節(jié)應(yīng)該特別注意。一些”材料“在所有頁(yè)面都通用。 在我們創(chuàng)建的基礎(chǔ)網(wǎng)站上,更新 /locallibrary/urls.py 文件。以確保每當(dāng)收到以catalog/開頭的URL時(shí),URLConf模塊中的catalog.urls 會(huì)處理剩余的字符串。 打開 urls.py ,復(fù)制下面代碼 urlpatterns = [ path('', views.index, name='index'),]
如果檢測(cè)到URL模式'',(views.index——在view.py中函數(shù)命名index() )將被調(diào)用。URL模式是Python 正則表達(dá)式 (RE)。我們將在本教程中進(jìn)一步介紹RE。 注意: 在 /locallibrary/locallibrary/urls.py urlpatterns += [
path('catalog/', include('catalog.urls')),
]
每當(dāng)Django 使用 include() (django.conf.urls.include()),它排除與該點(diǎn) 匹配URL的任何部分,并將剩余的字符串發(fā)送到隨附的 URLconf 進(jìn)行一步處理。 匹配的URL 實(shí)際上是 catalog/+<空字符串> (/catalog/ 假定是因?yàn)?include()是使用的方法)。如果我們收到一個(gè)URL的HTTP請(qǐng)求,我們的第一個(gè)視圖函數(shù)將被調(diào)用/catalog/。 此函數(shù)還說明了一個(gè)name參數(shù),此唯一標(biāo)識(shí)指定 URL 映射。你可以使用 "reverse" 映射—去動(dòng)態(tài)創(chuàng)建指定映射設(shè)計(jì)處理的資源的一個(gè)URL。例如,我們現(xiàn)在可以通過在我們的模版中創(chuàng)建以下鏈接到我們的主頁(yè): <a href="{% url 'index' %}">Home</a>.
注意: 我們當(dāng)然可以硬編碼上面的鏈接(如:<a href="/catalog/">Home</a>),但是如果我們改變了主頁(yè)的模式,模版將不再正確鏈接,使用反向網(wǎng)址映射會(huì)更靈活和強(qiáng)大。 視圖是處理HTTP請(qǐng)求的功能,根據(jù)需要從數(shù)據(jù)庫(kù)獲取數(shù)據(jù),通過使用HTML模板呈現(xiàn)此數(shù)據(jù)生成HTML頁(yè)面,然后以HTTP響應(yīng)返回HTML以顯示給用戶。索引視圖遵循此模型 - 它提取有關(guān)數(shù)據(jù)庫(kù)中有多少Book,BookInstance 可用 BookInstance 和 Author 記錄的信息,并將其傳遞給模板以進(jìn)行顯示。 打開catalog / views.py,并注意該文件已經(jīng)導(dǎo)入了 使用模板和數(shù)據(jù)生成HTML文件的 render() 快捷方式函數(shù)。 from django.shortcuts import render
# Create your views here.
復(fù)制文件底部的以下代碼。第一行導(dǎo)入我們將用于訪問所有視圖中數(shù)據(jù)的模型類。 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ù)。它還會(huì)獲取一個(gè)BookInstance狀態(tài)字段值為“a”(可用)的對(duì)象列表。您可以在前面的教程 (Django Tutorial Part 3: Using models > Searching for records)中找到更多關(guān)于如何訪問模型的信息。 在函數(shù)結(jié)束時(shí),我們將該函數(shù)稱為render()創(chuàng)建和返回HTML頁(yè)面作為響應(yīng)(此快捷方式函數(shù)包含許多其他函數(shù),簡(jiǎn)化了這種非常常見的用例)。它將原始request對(duì)象(an HttpRequest)作為參數(shù),具有數(shù)據(jù)占位符的HTML模板以及context變量(包含要插入到這些占位符中的數(shù)據(jù)的Python字典)。 我們將在下一節(jié)中詳細(xì)介紹模板和上下文變量; 讓我們創(chuàng)建我們的模板,以便我們可以向用戶顯示一些內(nèi)容 模版是定義一個(gè)文件(例如HTML頁(yè)面)的結(jié)構(gòu)與布局的文本文件,其中占位符用于表示實(shí)際內(nèi)容。Django將自動(dòng)在應(yīng)用程序“templates”目錄查找模版。所以例如,在我們剛剛加的索引頁(yè),render() 函數(shù)會(huì)期望能夠找到/locallibrary/catalog/templates/index.html這個(gè)文件,如何找不到該文件,則會(huì)引發(fā)錯(cuò)誤。如果保存以前的更改并返回到瀏覽器,你可以看到訪問 127.0.0.1:8000 現(xiàn)在將提供你一個(gè)相當(dāng)直觀的錯(cuò)誤信息"TemplateDoesNotExist at /catalog/“以及其他詳細(xì)信息。 注意: Django 將根據(jù)你的項(xiàng)目的設(shè)置文件, 來查看模版的許多位置 (在已安裝的應(yīng)用程序中進(jìn)行搜索是默認(rèn)設(shè)置). 你可以查閱更多關(guān)于Django如何找到模版以及它支持的模版格式在(Templates )。 擴(kuò)展模版索引模版將需要標(biāo)準(zhǔn)的HTML標(biāo)記頭部和正文,以及用于導(dǎo)航的部分(去我們尚為創(chuàng)建的網(wǎng)站其他的頁(yè)面)以及顯示一些介紹文本和我們書籍?dāng)?shù)據(jù)。我們網(wǎng)站上的每一頁(yè),大部分文字(HTML和導(dǎo)航結(jié)構(gòu))都是一樣的。Django模版語言不是強(qiáng)制開發(fā)人員在每個(gè)頁(yè)面中復(fù)制這個(gè)“樣板”,而是讓你聲明一個(gè)基本模版,然后再擴(kuò)展它,僅替換每個(gè)特定頁(yè)面不同的位置。 例如,基本模版 base_generic.html 可能看起來像下面的文本。正如你所見的,它包含一些“常見“HTML”和標(biāo)題,側(cè)邊欄和使用命名 block 和 endblock 模版標(biāo)記(粗體顯示)標(biāo)記的內(nèi)容部分。塊可以是空的,或者包含將被派生頁(yè)“默認(rèn)使用”的內(nèi)容。 注意: 模版標(biāo)簽就像你可以在模版中使用的函數(shù)循環(huán)列表,基于變量的值執(zhí)行條件操作等。除了模版標(biāo)簽,模版語法允許你引用模版變量(通過從視圖進(jìn)入模版),并使用模版過濾器,其中重新格式化變量(例如,將字符串設(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í),我們首先指定基本模版(使用 extends 模版標(biāo)簽—查看下一個(gè)代碼片段)。如果我們想要在模版中替換的章節(jié),會(huì)使用相同的 block/endblock 部分在基本模版表明。 例如,下面我們使用 extends 模版標(biāo)簽,并覆蓋 content 塊。生成的最終HTML頁(yè)面將具有基本模版中定義的所以HTML和結(jié)構(gòu)(包括你在title塊中定義的默認(rèn)內(nèi)容),但你新的 content 塊插入到了默認(rèn)的那塊。 base_generic.html 詳細(xì)會(huì)在下文中,請(qǐng)耐心往下看。
{% 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ì)劃的基本模版用于本地圖書館網(wǎng)站。正如所看到的,內(nèi)容包括一些HTML和定義塊 title ,sidebar 和 content。我們有默認(rèn)的 title(當(dāng)然我們可以改)和默認(rèn)的所以書籍和作者的鏈接列表 sidebar (我們可能并不會(huì)怎么改,但需要時(shí),我們通過把想法放入塊block中,比如想法是—允許范圍)。 注意: 我們?cè)俳榻B兩個(gè)額外的模版標(biāo)簽: url 和 load static 。下文中我們會(huì)詳細(xì)介紹。 創(chuàng)建一個(gè)新的文件 — /locallibrary/catalog/templates/base_generic.html — 寫入如下代碼 <!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" href="https://maxcdn./bootstrap/3.3.7/css/bootstrap.min.css">
<script src="https://ajax./ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<script src="https://maxcdn./bootstrap/3.3.7/js/bootstrap.min.js"></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>
該模版使用(并包含)JavaScript 和 Bootstrap (css框架)來改進(jìn)HTML頁(yè)面的布局和顯示,這個(gè)框架或者另一個(gè)客戶端網(wǎng)絡(luò)框架,這是快速創(chuàng)建一個(gè)可用頁(yè)面來適應(yīng)在不同瀏覽器尺寸和允許我們處理頁(yè)面呈現(xiàn)且不用一點(diǎn)細(xì)節(jié)—我們只需要專注在服務(wù)器端。 基本模版還引用了一個(gè)本地css文件 (styles.css) ,它提供了一些額外的樣式。 新建 /locallibrary/catalog/static/css/styles.css 如下: .sidebar-nav {
margin-top: 20px;
padding: 0;
list-style: none;
}
索引模版新建HTML文件 /locallibrary/catalog/templates/index.html 寫入下面代碼。第一行我們擴(kuò)展了我們的基本模版, 使用 content替換默認(rèn)塊。 {% 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 %}
注意:由于本網(wǎng)站就是通過django 來運(yùn)維,{{ 的模版標(biāo)簽 在上面代碼中會(huì)運(yùn)行,只能通過增加 \ 來轉(zhuǎn)義,而不能直接寫出“雙大括號(hào)”。 在動(dòng)態(tài)內(nèi)容部分,我們的占位符(模版變量),是給我們想要視圖的信息聲明。變量使用“雙大括號(hào)“ 或者“句柄“語法進(jìn)行標(biāo)記。 注意: 你可以輕松地識(shí)別是否使用變量或模版標(biāo)簽(函數(shù)),因?yàn)樽兞烤哂须p括號(hào)({{ num_books }}) 而標(biāo)記被包含在帶有百分比符號(hào) ({% extends "base_generic.html" %})的耽擱大括號(hào)中。 這里要注意的重要事情是這些變量用我們視圖函數(shù)render中的字典—注入 context (下面);當(dāng)渲染模版時(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},
)
在模版中引用靜態(tài)文件你的項(xiàng)目可能會(huì)使用靜態(tài)資源,包括javascript,css 和圖像。由于這些文件的位置可能不知道(或者可能會(huì)發(fā)生變化),則Django允許你指定你的模版相對(duì)于這些文件的位置 STATIC_URL 全局設(shè)置(默認(rèn)基本網(wǎng)站設(shè)置的值 STATIC_URL,以“/static/”,但你可能選擇在CDN和其他地方托管內(nèi)容)。 在模版中,你首先調(diào)用 load 指定“ static”去添加此模版庫(kù)(如下)。靜態(tài)加載后,你可以使用 static 模版標(biāo)簽,指定感興趣的文件相對(duì)URL <!-- Add additional CSS in static file -->
{% load static %}
<link rel="stylesheet" href="{% static 'css/styles.css' %}">
你可以用同樣的方式將圖像添加到頁(yè)面中: {% load static %}
<img src="{% static 'catalog/images/local_library_model_uml.png' %}" alt="My image" style="width:555px;height:540px;"/>
主題: 上面的更改指定文件所在的位置,但Django默認(rèn)不提供它們。當(dāng)我們created the website skeleton,我們?cè)谌諹RL映射器r (/locallibrary/locallibrary/urls.py) 中開發(fā)Web服務(wù)器提供服務(wù),你仍然需要安排它們?cè)谏a(chǎn)中投放。我們接下來看一看 更多內(nèi)容—Managing static files (Django docs). 鏈接URLs基本的模版引入 url 模版標(biāo)簽 <li><a href="{% url 'index' %}">Home</a></li>
此標(biāo)記url()使用您的urls.py中調(diào)用的函數(shù)的名稱 和相關(guān)視圖將從該函數(shù)接收的任何參數(shù)的值,并返回可用于鏈接到該資源的URL。 運(yùn)行 (python3 manage.py runserver) 和在瀏覽器中打開 http://127.0.0.1:8000/. I如果一切都正確設(shè)置,當(dāng)當(dāng)當(dāng)當(dāng)。 
注意:由于尚未定義這些網(wǎng)頁(yè)的網(wǎng)址,視圖和模板,因此您將無法使用“ 所有圖書和所有作者”鏈接(目前我們剛剛在base_generic.html模板中插入了這些鏈接的占位符) 以下是一些測(cè)試您熟悉模型查詢,視圖和模板的任務(wù)。 1. 在索引模板中聲明一個(gè)新的標(biāo)題塊,并更改頁(yè)面標(biāo)題以匹配此特定頁(yè)面。
2. 修改視圖以生成包含特定單詞(不區(qū)分大小寫)的類型計(jì)數(shù)和書數(shù),然后將這些字段添加到模板。 我們現(xiàn)在已經(jīng)為我們的網(wǎng)站創(chuàng)建了主頁(yè) - 一個(gè)HTML頁(yè)面,顯示數(shù)據(jù)庫(kù)中的一些記錄數(shù),并且鏈接到我們其他尚待創(chuàng)建的頁(yè)面。一路上,我們已經(jīng)學(xué)到了很多有關(guān)url映射器,視圖,使用我們的模型查詢數(shù)據(jù)庫(kù)的基本信息,如何從您的視圖傳遞信息到模板,以及如何創(chuàng)建和擴(kuò)展模板。 在我們的下一篇文章中,我們將基于我們的知識(shí)來創(chuàng)建其他四個(gè)頁(yè)面。
|