給Django的Admin新增自定義Action 並移除需要選擇物件的限制

畫星星高手發表於2020-08-26

不得不說,Django的Admin真的給開發帶來很多便利,這不,我又來折騰了,這次是新增自定義的action

這個自定義的Action可以看看官方文件的介紹,很詳細,不再贅述。

https://docs.djangoproject.com/en/3.0/ref/contrib/admin/actions/

介面效果

Django預設的新增完action是要選擇下面的物件才能提交的,不過我不需要啊,我就要簡簡單單點選開始抽獎就直接抽獎出來了,功夫不負有心人,我還是在Stack Overflow找到了解決方案,(果然是面向sof程式設計)

接下來介紹一下如何實現的~

定義Action

admin.py中寫程式碼:

@admin.register(models.PrizeLog)
class PrizeLogAdmin(admin.ModelAdmin):
    actions = ['draw_prize']

    def draw_prize(self, request, queryset):
        pass

    draw_prize.short_description = '開始抽獎'
    draw_prize.type = 'warning'
    draw_prize.confirm = '確認即開始抽獎併傳送中獎通知~'

這樣就把按鈕顯示出來了,但是現在點選完是不會執行draw_prize方法裡面的程式碼的,因為Django限制必須選擇至少一個物件才能進行action。

接下來我們曲線救國,來繞過這個限制。

移除限制

還是在這個Admin類中,編寫程式碼:

@admin.register(models.PrizeJoinLog)
class PrizeJoinLogAdmin(admin.ModelAdmin):
    actions = ['draw_prize']

    def changelist_view(self, request, extra_context=None):
        try:
            action = self.get_actions(request)[request.POST['action']][0]
            action_acts_on_all = action.acts_on_all
        except (KeyError, AttributeError):
            action_acts_on_all = False

        if action_acts_on_all:
            post = request.POST.copy()
            post.setlist(admin.helpers.ACTION_CHECKBOX_NAME,
                         self.model.objects.values_list('id', flat=True))
            request.POST = post

        return super(PrizeJoinLogAdmin, self).changelist_view(request, extra_context)

    def draw_prize(self, request, queryset):
        pass

    draw_prize.short_description = '開始抽獎'
    draw_prize.type = 'warning'
    draw_prize.confirm = '確認即開始抽獎併傳送中獎通知~'
    draw_prize.acts_on_all = True

注意上述程式碼,我們新增了changelist_view這個方法,並且最後一行給draw_prize加了個屬性acts_on_all 並賦值為True(無敵動態語言Python瞭解一下)

這樣在提交的時候,changelist_view檢查到action有個acts_on_all 屬性,就會自動帶上所有物件,相當於自動幫我們勾選了全部物件的意思。妙啊~

歡迎交流

不過這種方式感覺也不是很完美,如果大佬們有什麼更好的解決方法,歡迎留言討論~

參考資料

相關文章