iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 8
0

在剛開始接觸 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">&laquo; 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 &raquo;</a>
{% endif %}

我一直覺得 Django class based view 非常的優美,繼承適當的類別跟 Mixin 就可以完成功能,非常的棒。但 Django 內建的類別跟 Mixin 難免會有不足的地方,django-braces 套件就是在補足這不足的地方。django-braces 主要提供這三大類的 Mixins:Access Mixins、Form Mixins、Other Mixins。

  • Access Mixin 是跟權限、存取相關的 Mixin,在 Django 裡只有 LoginRequiredMixin,僅僅限制 View 只有登入使用者才能存取,但有些 View 會希望只有某些群組或是只有超級管理者才能存取,那這時候就可以用這些 Mixinx。
  • Form Mixins 是跟 Form 有關的 Mixins。
  • Other Mixins 是比較零碎的 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 的功能,就不再多做舉例了。

Access Mixins

  • LoginRequiredMixin:實作跟 Django 內建的 LoginRequiredMixin 差不多,使用者必須要登入後才能訪問 View。
  • PermissionRequiredMixin / MultiplePermissionsRequiredMixin / GroupRequiredMixin:這幾個 mixin 需要配合 Django Permissions 來使用,Django Permissions 可以指派群組跟權限給使用者,進而達到哪些使用者僅能存取這些 model 跟功能。
  • UserPassesTestMixin:符合檢查條件的使用者才可以訪問,繼承這個 Mixin 以後,需要實作 test_func,執行時會使用 test_func 來進行檢查。
  • SuperuserRequiredMixin:只有超級使用者可以訪問。
  • AnonymousRequiredMixin:任何使用者都可以訪問 View,但是如果使用者已經登入過的話,它會重導向到另外一個網址去。
  • StaffuserRequiredMixin:只有 Staff 使用者可以訪問。
  • SSLRequiredMixin:自動重導向到 https
  • RecentLoginRequiredMixin:登入經過指定時間後,會重新導向到登出頁面。

Form Mixins

  • CsrfExemptMixin:免除 CSRF 檢查,這是給 View 繼承用的。
  • UserFormKwargsMixin:為 form 提供 user 參數,這是給 View 繼承用的。
  • UserKwargModelFormMixin:從 form 的初始函數取出 user,這是給 form 繼承用的。
  • SuccessURLRedirectListMixin:主要是覆寫 get_success_url() 方法,覆寫後的 get_success_url() 會去讀取 success_list_url 這個屬性,這是給 View 繼承用的。
  • FormValidMessageMixin:可以指定在表單正確時,要顯示的訊息。這是給 View 繼承用的。
  • FormInvalidMessageMixin:可以指定在表單不正確時,要顯示的訊息。這是給 View 繼承用的。
  • FormMessagesMixin:這是前兩個的綜合。

Other Mixins

  • SetHeadlineMixin:會把 headline 屬性放到 View 的 context 去。
  • StaticContextMixin:會把 static_context 屬性合併到 View 的 context 去。
  • SelectRelatedMixin:覆寫 get_queryset() ,呼叫 queryset.select_related() 去查詢相關連的物件。
  • PrefetchRelatedMixin:覆寫 get_queryset(),呼叫 queryset.prefetch_related() 去查詢相關連的物件。(select_related 跟 prefetch_related 的差異可以參考後面的參考資料,主要是 Raw SQL 跟處理關連的方式不同)
  • JSONResponseMixin:把回應內容輸出為 JSON 。
  • JsonRequestResponseMixin:把回應內容輸出為 JSON,同時也把請求內容當做JSON來解析。
  • AjaxResponseMixin:判斷請求是否為 ajax,然後去呼叫自定的 _ajax() 函式
  • OrderableListMixin:增加自定排序欄位功能,View 在繼承這個 Mixin 以後,就可以在網址帶入 ordering 跟 order_by 參數來做排序。
  • CanonicalSlugDetailMixin:重導向到候選 slug 的網址
  • AllVerbsMixin:把所有的 HTTP verb 都以指定的方法來處理。
  • HeaderMixin:指定輸出的 HTTP 標頭。

結語

如果你也喜歡使用 Django class based view 來寫 View 的話,相信你在看到 django-braces 以後,也會非常喜歡,因為可以直接應用,少寫很多程式。

名詞解說

  • HTTP verb :HTTP 請求方法,一般常見的有 GET / POST / HEAD / DELETE / PATCH / PUT
  • slug:一個可以替代 object 主鍵的唯一識別

參考資料


上一篇
07. django-cors-header
下一篇
09. django-health-check
系列文
加速你的 Django 網站開發 - Django 的好用套件30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言