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

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