先決條件: | 完成之前的所有教學(xué)主題,包括 Django教程第5部分:創(chuàng)建我們的主頁。 |
---|---|
目的: | 了解在何處以及如何使用基于類的基本視圖,以及如何從URL中提取模式并將信息傳遞給視圖。 |
在本教程中,我們將完成第一個版本的 LocalLibrary >通過添加圖書和作者的列表和詳細信息頁面(或更準(zhǔn)確地說,我們將向您介紹如何實現(xiàn)圖書頁面,并讓您自己創(chuàng)建作者頁面)。
該過程類似于創(chuàng)建索引頁,我們在上一個教程中顯示。 我們?nèi)匀恍枰獎?chuàng)建URL地圖,視圖和模板。 主要的區(qū)別是,對于詳細頁面,我們將有額外的挑戰(zhàn),從URL中的模式提取信息并將其傳遞給視圖。 對于這些頁面,我們將演示一個完全不同類型的視圖:基于類的列表和詳細視圖。 這些可以顯著減少所需的視圖代碼量,使其更易于編寫和維護。
本教程的最后一部分將演示如何在使用基于類的列表視圖時對數(shù)據(jù)進行分頁。
圖書列表頁面將顯示頁面中所有可用圖書記錄的列表,使用以下網(wǎng)址訪問: catalog / books /
。 該頁面將顯示每個記錄的標(biāo)題和作者,標(biāo)題是相關(guān)聯(lián)的圖書詳細信息頁面的超鏈接。 該網(wǎng)頁與網(wǎng)站中的所有其他網(wǎng)頁具有相同的結(jié)構(gòu)和導(dǎo)航,因此可以擴展我們在上一教程中創(chuàng)建的基本模板( base_generic.html )。
打開 /catalog/urls.py ,然后復(fù)制下面粗體顯示的行。 與我們的索引映射非常類似,這個 url()
函數(shù)定義了一個正則表達式(RE)來匹配URL( r\'^ books / $\' 如果URL匹配( views.BookListView.as_view()
)和此特定映射的名稱,則將調(diào)用此函數(shù)。
urlpatterns = [ url(r'^$', views.index, name='index'), ? url(r'^books/$', views.BookListView.as_view(), name='books'), ]
這里的正則表達式匹配等于 books /
( ^
是字符串開始標(biāo)記, $
是字符串標(biāo)記的結(jié)尾)的URL。 如前面的教程中所討論的,URL必須已經(jīng)具有匹配的 / catalog
,因此視圖將實際調(diào)用URL: / catalog / books /
。
視圖函數(shù)具有與以前不同的格式 - 這是因為此視圖實際上將實現(xiàn)為類。 我們將繼承一個現(xiàn)有的通用視圖函數(shù),它已經(jīng)完成了我們想要此視圖函數(shù)所做的大部分工作,而不是從頭開始編寫自己的視圖函數(shù)。
對于基于Django類的視圖,我們通過調(diào)用類方法 as_view()
來訪問一個合適的視圖函數(shù)。 這將完成創(chuàng)建類的實例的所有工作,并確保為傳入的HTTP請求調(diào)用正確的處理程序方法。
我們可以很容易地將書列表視圖作為常規(guī)函數(shù)(就像我們以前的索引視圖一樣),它將查詢數(shù)據(jù)庫中的所有書,然后調(diào)用 render()
將列表傳遞給 指定模板。 相反,我們將使用基于類的通用列表視圖(ListView) - 從現(xiàn)有視圖繼承的類。 因為通用視圖已經(jīng)實現(xiàn)了我們所需要的大多數(shù)功能,并且遵循Django最佳實踐,我們將能夠創(chuàng)建一個更健壯的列表視圖,代碼更少,重復(fù)次數(shù)更少,最終減少維護。
打開 catalog / views.py ,然后將以下代碼復(fù)制到文件底部:
from django.views import generic class BookListView(generic.ListView): model = Book
而已! 通用視圖將查詢數(shù)據(jù)庫以獲取指定模型的所有記錄( Book
),然后渲染位于 /locallibrary/catalog/templates/catalog/book_list.html (我們將在下面創(chuàng)建)。 在模板中,您可以使用名為 object_list
或 book_list
的模板變量訪問圖書列表(即通常為" the_model_name _list 代碼>")。
注意:模板位置的尷尬路徑不是錯誤印記 - 通用視圖會在 / application_name / the_model_name
應(yīng)用程序的 / application_name / templates /
目錄()中的
( / list.html
catalog / book_list.html
> / catalog / templates /)。
您可以添加屬性以更改上述默認行為。 例如,如果您需要具有使用此相同模型的多個視圖,則可以指定另一個模板文件,或者如果 book_list
對您的特定模板使用不直觀,則可能需要使用不同的模板變量名稱 -案件。 可能最有用的變化是更改/過濾返回的結(jié)果子集 - 因此,不是列出所有圖書,而是列出其他用戶閱讀的前5個圖書。
class BookListView(generic.ListView): model = Book context_object_name = 'my_book_list' # your own name for the list as a template variable queryset = Book.objects.filter(title__icontains='war')[:5] # Get 5 books containing the title war template_name = 'books/my_arbitrary_template_name_list.html' # Specify your own template name/location
雖然我們不需要這樣做,你也可以覆蓋一些類方法。
例如,我們可以覆蓋 get_queryset()
方法來更改返回的記錄列表。 這比設(shè)置 queryset
屬性更靈活,就像我們在前面的代碼片段中做的那樣(雖然在這種情況下沒有真正的好處):
class BookListView(generic.ListView): model = Book ? ? def get_queryset(self): ? ? ? ? return Book.objects.filter(title__icontains='war')[:5] # Get 5 books containing the title war
我們還可以覆蓋 get_context_data()
,以便將其他上下文變量傳遞給模板(例如,默認情況下會傳遞書籍列表)。 下面的片段顯示了如何向上下文添加一個名為"some_data"的變量(它將作為模板變量使用)。
class BookListView(generic.ListView): model = Book ? ? def get_context_data(self, **kwargs): ? ? ? ? # Call the base implementation first to get a context ? ? ? ? context = super(BookListView, self).get_context_data(**kwargs) ? ? ? ? # Get the blog from id and add it to the context ? ? ? ? context['some_data'] = 'This is just some data' ? ? ? ? return context
當(dāng)這樣做時,重要的是遵循上面使用的模式:
注意:查看內(nèi)置 - 在基于類的通用視圖(Django docs)中有更多可以做的事例。
創(chuàng)建HTML文件 /locallibrary/catalog/templates/catalog/book_list.html ,然后在下面的文本中復(fù)制。 如上所述,這是基于通用類的列表視圖(對于名為目錄
的應(yīng)用程序中名為 Book
的模型)所期望的默認模板文件。
通用視圖的模板就像任何其他模板(雖然傳遞給模板的上下文/信息當(dāng)然可能不同)。 與我們的 index 模板一樣,我們在第一行中擴展我們的基本模板,然后替換名為 content
的塊。
{% extends "base_generic.html" %} {% block content %} ? ? <h1>Book List</h1> ? ? {% if book_list %} ? ? <ul> ? ? ? {% for book in book_list %} ? ? ? <li> ? ? ? ? <a href="{{ book.get_absolute_url }}">{{ book.title }}</a> ({{book.author}}) ? ? ? </li> ? ? ? {% endfor %} ? ? </ul> ? ? {% else %} ? ? ? <p>There are no books in the library.</p> ? ? {% endif %} ? ? ?? {% endblock %}
默認情況下,視圖傳遞上下文(書籍列表)為 object_list
和 book_list
(別名;將起作用)。
我們使用 如果
, else
和 endif
模板標(biāo)簽來檢查 book_list
是否已定義并且不為空。 它是空的( else
子句),然后我們顯示文本,說明沒有圖書要顯示。 如果它不為空,那么我們遍歷書的列表。
{% if book_list %} <!-- code here to list the books --> {% else %} <p>There are no books in the library.</p> {% endif %}
上述條件僅檢查一種情況,但您可以使用 elif
模板標(biāo)記(例如 {%elif var2%}
)對其他條件進行測試。 有關(guān)條件運算符的詳情,請參閱:如果, class ="external"> ifequal / ifnotequal 和 https://docs.djangoproject.com/en/1.10/ref/templates/builtins/#ifchanged"class ="external"> ifchanged 在 en / 1.10 / ref / templates / builtins"class ="external">內(nèi)置模板標(biāo)簽和過濾器(Django Docs)。
該模板使用 和 endfor
代碼>模板標(biāo)記循環(huán)訪問圖書列表,如下所示。 每次迭代用當(dāng)前列表項的信息填充 book
模板變量。
{% for book in book_list %} <li> <!-- code here get information from each book item --> </li> {% endfor %}
雖然這里不使用,但在循環(huán)內(nèi)Django還將創(chuàng)建其他變量,您可以使用它來跟蹤迭代。 例如,您可以測試 forloop.last
變量,以便在上次運行循環(huán)時執(zhí)行條件處理。
循環(huán)中的代碼為每本書創(chuàng)建一個列表項,該列表項顯示標(biāo)題(作為尚未創(chuàng)建的詳細視圖的鏈接)和作者。
<a href="{{ book.get_absolute_url }}">{{ book.title }}</a> ({{book.author}})
我們使用"點符號"(例如 book.title
和 book.author
)訪問關(guān)聯(lián)的圖書記錄的字段 在 book
項下是字段名(如模型中定義)。
我們還可以在模板中從模板中調(diào)用函數(shù) - 在這種情況下,我們調(diào)用 Book.get_absolute_url()
獲取一個URL, 。 這個工作提供的函數(shù)沒有任何參數(shù)(沒有辦法傳遞參數(shù)!)
注意:在模板中調(diào)用函數(shù)時,我們必須小心處理"副作用"。 這里我們只是得到一個顯示的URL,但是一個函數(shù)可以做任何事情 - 我們不想刪除我們的數(shù)據(jù)庫(例如)只是通過渲染我們的模板!
打開基本模板( / locallibrary / catalog / templates / base_generic.html ),然后在網(wǎng)址中插入 {%url\'books\'%} 所有圖書的鏈接,如下所示。 這將啟用所有頁面的鏈接(我們可以成功地把它放在位,現(xiàn)在我們已經(jīng)創(chuàng)建了"書籍"URL映射器)。
<li><a href="{% url 'index' %}">Home</a></li> <li><a href="{% url 'books' %}">All books</a></li> <li><a href="">All authors</a></li>
您將無法構(gòu)建圖書列表,因為我們?nèi)匀蝗鄙僖蕾図?- 圖書詳細信息頁面的URL地圖,需要創(chuàng)建指向各個圖書的超鏈接。 在下一節(jié)后,我們將顯示列表和詳細信息視圖。
書詳細信息頁將顯示關(guān)于使用網(wǎng)址 catalog / book / < id>
(其中 < id>
是圖書的主鍵)。 除了 Book
模型(作者,摘要,ISBN,語言和流派)中的字段,我們還會列出可用副本的詳細信息( BookInstances
), 狀態(tài),預(yù)期的返回日期,印記和ID,這將使我們的讀者不僅了解這本書,而且確認是否/何時可用。
打開 /catalog/urls.py 并添加" book-detail "URL映射器,如下面的粗體所示。 這個 url()
函數(shù)定義一個模式,關(guān)聯(lián)的基于類的詳細視圖和一個名稱。
urlpatterns = [ url(r'^$', views.index, name='index'), ? url(r'^books/$', views.BookListView.as_view(), name='books'), ? url(r'^book/(?P<pk>\d+)$', views.BookDetailView.as_view(), name='book-detail'), ]
與我們以前的映射器不同,在這種情況下,我們使用正則表達式(RE)匹配一個真正的"模式",而不只是一個字符串。 這個特定的RE所做的是與以 book /
開頭的任何網(wǎng)址匹配,后跟在行標(biāo)記結(jié)束之前的一個或多個數(shù)字(數(shù)字)。 在執(zhí)行匹配時,它"捕獲"數(shù)字,并將它們作為名為 pk
的參數(shù)傳遞給視圖函數(shù)。
注意:如前所述,我們匹配的網(wǎng)址實際上是 catalog / book /< digits>
(因為我們位于目錄應(yīng)用程序 代碼> / catalog / )。
重要:通用基于類的詳細視圖期望傳遞名為pk的參數(shù)。 如果你正在編寫我們自己的函數(shù)視圖,你可以使用任何你喜歡的參數(shù)名,或者確實在一個未命名的參數(shù)傳遞信息。
正則表達式是一個令人難以置信的強大的模式映射工具。 我們之前已經(jīng)避免了很多關(guān)于它們的事情,因為我們在URL中匹配硬編碼的字符串(而不是模式),并且坦率地說,它們對初學(xué)者來說是非常直觀和可怕的。
注意:不要驚慌! 我們將匹配的模式很簡單,在很多情況下都有很好的文檔!
首先要知道的是,正則表達式通常應(yīng)該使用原始字符串文字語法來聲明(即它們?nèi)缦滤? r\'
聲明模式匹配所需的語法的主要部分是:
符號 | 含義 |
---|---|
^ | 匹配文本的開頭 |
$ | 匹配文本的結(jié)尾 |
\d | 匹配數(shù)字(0,1,2,... 9) |
\w | 匹配字詞字符,例如 字母表中的任何大寫或小寫字符,數(shù)字或下劃線字符(_) |
+ | Match one or more of the preceding character. For example, to match one or more digits you would use \d+ . To match one or more "a" characters, you could use a+
|
* | Match zero or more of the preceding character. For example, to match nothing or a word you could use \w*
|
() | 捕獲括號內(nèi)的模式部分。 任何捕獲的值都將作為未命名參數(shù)傳遞到視圖(如果捕獲多個模式,則相關(guān)參數(shù)將按聲明捕獲的順序提供)。 |
(?P<name>...) | 捕獲模式(由...指示)作為命名變量(在本例中為"名稱")。 捕獲的值將傳遞到具有指定名稱的視圖。 因此,您的視圖必須聲明具有相同名稱的參數(shù)! |
[] | 與集合中的一個字符匹配。 例如,[abc]將匹配\'a\'或\'b\'或\'c\'。 [ - \\ w]將匹配" - "字符或任何字字符。 |
大多數(shù)其他字符可以采取字面意思!
讓我們考慮幾個真實的模式例子:
模式 | 描述 |
---|---|
r'^book/(?P<pk>\d+)$' |
這是我們的url映射器中使用的RE。 它與在行開頭有 它還捕獲所有數(shù)字(?P 例如,這將匹配 |
r'^book/(\d+)$' | 此匹配與上述情況相同的網(wǎng)址。 捕獲的信息將作為未命名的參數(shù)發(fā)送到視圖。 |
r'^book/(?P<stub>[-\w]+)$' |
此操作與在行開頭有 這是一個相當(dāng)?shù)湫偷哪J綖?存根"。 存根是用于數(shù)據(jù)的基于URL的基于字的主鍵。 如果您希望圖書網(wǎng)址更具信息性,則可以使用存根。 例如 |
您可以在一個匹配中捕獲多個模式,從而在URL中編碼大量不同的信息。
注意:作為一個挑戰(zhàn),請考慮如何對網(wǎng)址進行編碼,以列出在特定年份,月份,日期和RE中發(fā)布的所有可用于匹配的圖書。
我們在這里沒有使用,但您可能會發(fā)現(xiàn)有價值的一個功能是,您可以聲明并傳遞 views-extra-options"class ="external">其他選項。 選項聲明為一個字典,作為第三個未命名的參數(shù)傳遞給 url()
函數(shù)。 如果要對多個資源使用相同的視圖,并傳遞數(shù)據(jù)以配置其在每種情況下的行為(在每種情況下我們提供不同的模板),此方法可能很有用。
url(r'^/url/$', views.my_reused_view, {'my_template_name': 'some_path'}, name='aurl'), url(r'^/anotherurl/$', views.my_reused_view, {'my_template_name': 'another_path'}, name='anotherurl'),
注意:將兩個額外選項和命名捕獲的模式作為命名的參數(shù)傳遞給視圖。 如果對捕獲的模式和額外選項使用同名,則只會將捕獲的模式值發(fā)送到視圖(在附加選項中指定的值將被刪除)。
打開 catalog / views.py ,然后將以下代碼復(fù)制到文件底部:
class BookDetailView(generic.DetailView): ? ? model = Book
而已! 您現(xiàn)在需要做的是創(chuàng)建一個名為 /locallibrary/catalog/templates/catalog/book_detail.html 的模板,該視圖將為其傳遞特定 Book
的數(shù)據(jù)庫信息 >記錄由URL映射器提取。 在模板中,您可以使用名為 object
或 book
的模板變量訪問書籍列表(即通常為" the_model_name
>")。
如果需要,可以更改模板中使用的模板以及用于引用該書的上下文對象的名稱。 您還可以覆蓋方法,例如,向上下文添加附加信息。
如果一個請求的記錄不存在,那么通用的基于類的細節(jié)視圖將自動引發(fā)一個Http404異常 - 在生產(chǎn)中,這將自動顯示一個適當(dāng)?shù)?找不到資源"頁面,如果需要可以自定義。
只是為了讓你了解這是如何工作的,下面的代碼片段演示了如何實現(xiàn)基于類的視圖作為一個函數(shù),如果你不使用通用基于類的細節(jié)視圖。
def book_detail_view(request,pk): try: book_id=Book.objects.get(pk=pk) except Book.DoesNotExist: raise Http404("Book does not exist") ? #book_id=get_object_or_404(Book, pk=pk) return render( request, 'catalog/book_detail.html', context={'book':book_id,} )
視圖首先嘗試從模型中獲取特定的書記錄。 如果這個失敗,視圖應(yīng)該引發(fā)一個 Http404
異常,表示該書"找不到"。 最后一步是像往常一樣,使用模板名稱和 context
參數(shù)(作為字典)調(diào)用 render()
。
注意:如果未找到記錄,則 get_object_or_404()
(如上所示已注釋掉)是提高 Http404
異常的一個方便的快捷方式。
創(chuàng)建HTML文件 /locallibrary/catalog/templates/catalog/book_detail.html ,并為其提供以下內(nèi)容。 如上所述,這是基于通用類的 detail 視圖(在名為目錄的應(yīng)用程序中名為
代碼>)。 Book
的模型)
{% extends "base_generic.html" %} {% block content %} <h1>Title: {{ book.title }}</h1> <p><strong>Author:</strong> <a href="">{{ book.author }}</a></p> <!-- author detail link not yet defined --> <p><strong>Summary:</strong> {{ book.summary }}</p> <p><strong>ISBN:</strong> {{ book.isbn }}</p>? <p><strong>Language:</strong> {{ book.language }}</p> ? <p><strong>Genre:</strong> {% for genre in book.genre.all %} {{ genre }}{% if not forloop.last %}, {% endif %}{% endfor %}</p> ? <div style="margin-left:20px;margin-top:20px"> <h4>Copies</h4> {% for copy in book.bookinstance_set.all %} <hr> <p class="{% if copy.status == 'a' %}text-success{% elif copy.status == 'd' %}text-danger{% else %}text-warning{% endif %}">{{ copy.get_status_display }}</p> {% if copy.status != 'a' %}<p><strong>Due to be returned:</strong> {{copy.due_back}}</p>{% endif %} <p><strong>Imprint:</strong> {{copy.imprint}}</p> <p class="text-muted"><strong>Id:</strong> {{copy.id}}</p> {% endfor %} </div> {% endblock %}
上面的tempate中的作者鏈接有一個空的網(wǎng)址,因為我們還沒有創(chuàng)建一個作者詳細頁面。 一旦存在,您應(yīng)該更新URL如下:
<a href="{% url 'author-detail' book.author.pk %}">{{ book.author }}</a>
雖然有點大,幾乎在這個模板中的一切都已經(jīng)描述過:
for
loops to loop through lists of objects.book
; we could also use "object
")我們之前沒有看到的一個有趣的事情是函數(shù) book.bookinstance_set.all()
。 這個方法是由Django"自動地"構(gòu)造的,以返回與特定 Book
相關(guān)聯(lián)的 BookInstance
記錄集。
{% for copy in book.bookinstance_set.all %} <!-- code to iterate across each copy/instance of a book --> {% endfor %}
需要此方法,因為您只在關(guān)系的"一"端聲明了一個 ForeignKey
(一對多)字段。 因為你沒有在其他("many")模型中聲明關(guān)系,所以它沒有任何字段來獲取關(guān)聯(lián)記錄的集合。 為了克服這個問題,Django構(gòu)造了一個可以使用的適當(dāng)命名的"反向查找"函數(shù)。 該函數(shù)的名稱由下殼構(gòu)造,其中 ForeignKey
被聲明的模型名稱后面跟 _set
(即在 Book code>是
bookinstance_set()
)。
注意:此處我們使用 all()
獲取所有記錄(默認)。 雖然您可以使用 filter()
方法獲取代碼中的記錄子集,但是您無法在模板中直接執(zhí)行此操作,因為您不能為函數(shù)指定參數(shù)。
在這一點上,我們應(yīng)該創(chuàng)建顯示圖書列表和圖書詳細頁面所需的一切。 運行服務(wù)器( python3 manage.py runserver
),然后打開瀏覽器 http://127.0。 0.1:8000 / 。
警告:不要點擊任何作者或作者詳細信息鏈接 - 您將在挑戰(zhàn)中創(chuàng)建這些鏈接!
點擊所有圖書鏈接以顯示圖書列表。
; width:823px;">
然后點擊您的某本書的鏈接。 如果一切設(shè)置正確,您應(yīng)該看到類似以下屏幕截圖。
; width:926px;">
如果你只有幾個記錄,我們的書列表頁面看起來很好。 然而,當(dāng)你進入幾十或幾百的記錄,頁面將逐漸加載(和有太多的內(nèi)容,以適當(dāng)瀏覽)。 此問題的解決方案是在列表視圖中添加分頁,減少每個頁面上顯示的項目數(shù)。
Django對分頁提供了極好的內(nèi)置支持。 更好的是,這是基于類的列表視圖,所以你不必做太多的啟用它!
打開 catalog / views.py ,然后添加以粗體顯示的 paginate_by
行。
class BookListView(generic.ListView): model = Book paginate_by = 10
使用此添加,只要您有超過10條記錄,視圖將開始分頁發(fā)送到模板的數(shù)據(jù)。 使用GET參數(shù)訪問不同的網(wǎng)頁 - 要訪問第2頁,您需要使用網(wǎng)址: / catalog / books / ?page = 2
。
現(xiàn)在數(shù)據(jù)已分頁,我們需要添加對模板的支持以滾動瀏覽結(jié)果集。 因為我們可能想在所有列表視圖中執(zhí)行此操作,我們將以可添加到基本模板的方式執(zhí)行此操作。
打開 / locallibrary / catalog / templates / base_generic.html ,并在我們的內(nèi)容塊下面的下面的分頁塊中復(fù)制(下面粗體突出顯示)。 代碼首先檢查是否在當(dāng)前頁面上啟用了分頁。 如果是,則它適當(dāng)?shù)靥砑酉乱粋€和上一個鏈接(以及當(dāng)前頁碼)。
{% block content %}{% endblock %} {% block pagination %} {% if is_paginated %} <div class="pagination"> <span class="page-links"> {% if page_obj.has_previous %} <a href="{{ request.path }}?page={{ page_obj.previous_page_number }}">previous</a> {% endif %} <span class="page-current"> Page {{ page_obj.number }} of {{ page_obj.paginator.num_pages }}. </span> {% if page_obj.has_next %} <a href="{{ request.path }}?page={{ page_obj.next_page_number }}">next</a> {% endif %} </span> </div> {% endif %} {% endblock %}
page_obj
是 Paginator 如果在當(dāng)前頁面上使用分頁,則將存在的對象。 它允許您獲取有關(guān)當(dāng)前頁面,上一頁,有多少頁面等的所有信息。
我們使用 {{request.path}}
獲取用于創(chuàng)建分頁鏈接的當(dāng)前網(wǎng)頁網(wǎng)址。 這是有用的,因為它獨立于我們分頁的對象。
而已!
下面的屏幕截圖顯示了分頁的樣子 - 如果您沒有在數(shù)據(jù)庫中輸入超過10個標(biāo)題,那么您可以通過降低 paginate_by
行中指定的數(shù)字更容易地測試它, strong> catalog / views.py 文件。 為了得到下面的結(jié)果,我們將它改為 paginate_by = 2
。
分頁鏈接顯示在底部,根據(jù)您所在的頁面顯示下一個/上一個鏈接。
; width:924px;">
本文中的挑戰(zhàn)是創(chuàng)建作者詳細信息和列出完成項目所需的視圖。 這些應(yīng)在以下網(wǎng)址提供:
catalog/authors/
?— The list of all authors.catalog/author/<id>
?—?The detail view for the specific author?with a primary key field named?<id>
URL映射器和視圖所需的代碼應(yīng)該與上面創(chuàng)建的 Book
列表和詳細視圖幾乎相同。 模板將是不同的,但會共享類似的行為。
注意:
<p><strong>Author:</strong> <a href="{% url 'author-detail' book.author.pk %}">{{ book.author }}</a></p>
完成后,您的網(wǎng)頁應(yīng)該像下面的屏幕截圖。
; width:825px;">
恭喜,我們的基本庫功能現(xiàn)已完成!
在本文中,我們學(xué)習(xí)了如何使用基于類的列表和詳細視圖,并使用它們來創(chuàng)建頁面來查看我們的書籍和作者。 一路上,我們學(xué)習(xí)了使用正則表達式的模式匹配,以及如何將數(shù)據(jù)從URL傳遞到視圖。 我們還學(xué)習(xí)了使用模板的更多技巧。 最后,我們展示了如何對列表視圖進行分頁,以便我們的列表是可管理的,即使我們有很多記錄。
在我們的下一篇文章中,我們將擴展此庫以支持用戶帳戶,從而演示用戶身份驗證,權(quán)限,會話和表單。
更多建議: