[Python+Django]初心者筆記7(建立list清單網頁,建立資料明細頁,list清單網頁分頁顯示paging)
接下來要建立Book的list清單網頁,請在/catalog/urls.py裡面修改urlpatterns變數加入:
path('books/', views.BookListView.as_view(), name='books'),
所以整個urlpatterns變數將會變成像是下面這樣
urlpatterns = [
#views.index:使用vews.py裡面定義的function:index()
#name='index':.html的樣本template檔裡面,要寫href超連結語法的話,就會用到
path('', views.index, name='index'),
#加入Books資料表的list清單網頁的url mapping
path('books/', views.BookListView.as_view(), name='books'),
#加入Books資料表的詳細資料網頁的url mapping
path('book/<int:pk>', views.BookDetailView.as_view(), name='book-detail'),
]
接著在/catalog/views.py下面加入:
#建立Book資料的List清單網頁
from django.views import generic
class BookListView(generic.ListView):
model = Book
#透過定義get_queryset()就可以自己定義想要的資料
#沒有要自定義的話就註解掉get_queryset()
def get_queryset(self):
return Book.objects.filter(title__icontains='bike')[:5] #取前五筆資料,title包含關鍵字'bike'的
#等等要去哪個路徑找.html檔案
#不定義這個template_name的話,Django就會去預設的路徑尋找.html
#預設的路徑是:/locallibrary/catalog/templates/catalog/book_list.html
#不過目前暫時程式碼設定路徑的方式跟預設一樣就好
template_name = '/locallibrary/catalog/templates/catalog/book_list.html'
#get_context_data()是用來建立自訂的Server side variable的
#跟.Net MVC也挺像的
def get_context_data(self, **kwargs):
# Call the base implementation first to get the context
context = super(BookListView, self).get_context_data(**kwargs)
# Create any data and add it to the context
context['some_data'] = 'This is just some data'
return context
#這是分頁機制, 以下設定一頁的最多資料筆數 = 1
paginate_by = 1
接著請新增這個超級無敵奇怪路徑下的.html檔案(路徑的資料夾請自行新增):/locallibrary/catalog/templates/catalog/book_list.html
html檔的內容如下
{% extends "base_generic.html" %}
{% block content %}
<h1>Book List</h1>
<!-- 在views.py的class BookListView定義的get_queryset()
會自動傳送一個預設的變數名稱book_list過來,當作list清單網頁的資料 -->
{% 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 %}
然後再來建立Book的明細網頁,請在catalog/views.py加入:
#從db取得某本Book的明細資料
#不需要寫什麼特殊的Query語法,Django將會自動做好binding
class BookDetailView(generic.DetailView):
model = Book
接著需建立Book的資料明細頁,請新增一個.html檔:/locallibrary/catalog/templates/catalog/book_detail.html
路徑資料夾請自行新增,而html檔的內容如下:
{% extends "base_generic.html" %}
{% block content %}
<h1>Title: {{ book.title }}</h1>
{% comment %} <p><strong>Author:</strong> <a href="{% url 'author-detail' book.author.pk %}">{{ book.author }}</a></p> <!-- author detail link not yet defined --> {% endcomment %}
<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>
{% comment %} book.bookinstance_set由來:當models.py只有定義單方向的bookinstance=>book的foreign key的關係
的時候,Django提供了特殊的用法 OOXX_set,讓book=>bookinstance雖沒有被定義,也可以使用 {% endcomment %}
{% for copy in book.bookinstance_set.all %}
<hr>
<p class="{% if copy.status == 'a' %}text-success{% elif copy.status == 'm' %}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 %}
如此一來清單頁以及明細頁就完成了
清單頁:
明細頁:上面明細頁的Author的foreign key的超連結部分尚未實做,將於下個文章說明
這篇先這樣…
參考資料:
Django Tutorial Part 6: Generic list and detail views
https://developer.mozilla.org/en-US/docs/Learn/Server-side/Django/Generic_views