在剛開始接觸 Django 的時候,找來找去,通常都是找到以 Function based view 的範例來寫 View。以這種方式寫了幾次之後,會覺得應該可以把流程萃取為 pattern ,但始終沒有去做。後來才發現 Django 可以用 Class based view 來寫 View,去研讀以後,發現這真的是很棒。
舉個例子來說,網站要提供一個「文章列表」的功能,那麼可以這樣來寫
# 延續之前的 news app
from django.contrib.auth.mixins import LoginRequiredMixin
from django.views.generic import ListView
from news.models import Article
class ArticleListView(LoginRequiredMixin, ListView):
model = Article
template_name = 'news/article_list.html'
paginate_by = 10
程式非常的精簡,而且還包含分頁,這樣就寫完了。
在 template 裡,只要依據 object_list 跟 page_obj 來顯示就可以。(註:Django 官方網站文件是用 page_obj,在原始碼裡,object_list 等於 page_obj.object_list,iterate page_obj 跟 iterate page_obj.object_list 是一樣的。)
<ul>
{% for object in object_list %}
<li>{{object.title}}</li>
{% endfor %}
</ul>
{% # 顯示分頁 %}
{% if page_obj.has_previous %}
<a href="?page=1">« first</a>
<a href="?page={{ page_obj.previous_page_number }}">previous</a>
{% endif %}
<span class="current">
Page {{ page_obj.number }} of {{ page_obj.paginator.num_pages }}.
</span>
{% if page_obj.has_next %}
<a href="?page={{ page_obj.next_page_number }}">next</a>
<a href="?page={{ page_obj.paginator.num_pages }}">last »</a>
{% endif %}
我一直覺得 Django class based view 非常的優美,繼承適當的類別跟 Mixin 就可以完成功能,非常的棒。但 Django 內建的類別跟 Mixin 難免會有不足的地方,django-braces 套件就是在補足這不足的地方。django-braces 主要提供這三大類的 Mixins:Access Mixins、Form Mixins、Other Mixins。
等等,Mixin ?? 嗯,對,Mixin 簡單的說,是 Composite pattern 的概念,在 Django 裡,這些 Mixin 是具有特定功能的類別,在繼承這些 Mixin 以後,類別就擁有了 Mixin 的功能。我不知道這名詞來源是哪裡,但我第一次看到時,是在 Ruby 裡看到的。
poetry add django-braces
使用上非常簡單,就是繼承,然後填寫 Mixin 所需要的設定就可以。
以 StaffRequiredMixin 為例,這個 View 就只能允許使用者的 is_staff 欄位為真時,才能存取。
# 範例引用自:https://django-braces.readthedocs.io/en/latest/access.html#staffuserrequiredmixin
from django.views.generic import TemplateView
from braces import views
class SomeStaffuserView(views.LoginRequiredMixin,
views.StaffuserRequiredMixin,
TemplateView):
template_name = u"path/to/template.html"
再以 HeaderMixin 為例,這個 View 會額外送出 X-Header-Sample 跟 X-Some-Number 這兩個 HTTP 標頭
# 範例引用自:https://django-braces.readthedocs.io/en/latest/other.html#headermixin
from django.views import TemplateView
from braces.views import HeaderMixin
class StaticHeadersView(HeaderMixin, TemplateView):
template_name = "some/headers.html"
headers = {
'X-Header-Sample': 'some value',
'X-Some-Number': 42
}
以下就簡單說明各個 Mixin 的功能,就不再多做舉例了。
如果你也喜歡使用 Django class based view 來寫 View 的話,相信你在看到 django-braces 以後,也會非常喜歡,因為可以直接應用,少寫很多程式。