前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Django 进阶学习 - 动态actions

Django 进阶学习 - 动态actions

作者头像
用户1416054
发布2018-08-02 11:40:02
4010
发布2018-08-02 11:40:02
举报
文章被收录于专栏:JackeyGao的博客

Django 进阶学习 - 动态actions

Posted May 03, 2016

Django后台默认只有一个动作Delete selected xxxxs, 那么如果自定义动作该怎么办, 也很容易, 直接写个类似于这种的函数

Python

代码语言:javascript
复制
def make_published(modeladmin, request, queryset):
    queryset.update(status='p')

然后绑定到ModelAdmin的actions属性

admin.py

Python

代码语言:javascript
复制
class TriggerAdmin(admin.ModelAdmin):
    empty_value_display = u'无规则'
    list_display = ('__str__', 'id')
    search_fields = ('description',)
    list_filter = (IpFilter, 't_type')
    actions = (make_published,) #指定自定义actions

action在程序启动后就会正常工作, 现在我有个项目需要根据一张表(role表)来动态扩展动作, 所以这种方法没有办法扩展。 总不能在role表加一个数据就要重启django把? 显然不能这样做, 当然django有动态生成action的方法, 那就是admin.ModelAdminget_actions()方法

首先写个闭包

根据role生成action function

actions.py

Python

代码语言:javascript
复制
from django.utils.translation import ugettext as _, ugettext_lazy
from controller.models import SwitchRole
from controller.models import ConvergeRole

def _with_role(role, switch=True):
    """闭包实现, 设置role, switch为通用变量,  返回一个action函数"""

    # 根据role类型判断字段类型
    if isinstance(role, SwitchRole):
        field_name = "switch_role"
    elif isinstance(role, ConvergeRole):
        field_name = "converge_role"
    else:
        return None

    def set_selected(modeladmin, request, queryset):
        """
        规则动作
        """
        # 根据开关选项, 来判断字段value
        kwargs = {}
        if switch:
            field_value = role.pk
        else:
            field_value = None

        kwargs[field_name] = field_value
        return queryset.update(**kwargs)

    set_selected.short_description = ugettext_lazy(u"设置规则为: %s" % role)
    set_selected.__name__ = "set_role_%s_%s" % (field_name, role.pk)
    return set_selected

注意: set_selected.short_description为后台管理界面actions下拉菜单显示的文本, set_selected.__name__ 是函数的名称, 由于我们是多个,所以函数的名称一定要唯一.

下面重写get_actions()

admin.py

Python

代码语言:javascript
复制
class TriggerAdmin(admin.ModelAdmin):
    empty_value_display = u'无规则'
    list_display = ('__str__', 'id', 'ip', 't_type',
            'get_converge', 'get_switch', 'level')
    search_fields = ('description',)
    list_filter = (IpFilter, 't_type', 'converge_role', 'switch_role', 'level')

    def get_actions(self, request):
        # 设置Role动作
        fns = [ _with_role(i) for i in SwitchRole.objects.all() ]
        fns += [_with_role(i) for i in ConvergeRole.objects.all()]

        # 清空Role动作
        if SwitchRole.objects.all():
            role = _with_role(SwitchRole.objects.all()[0], switch=False)
            role.__name__ = 'remove_switch_role'
            role.short_description = ugettext_lazy(u"清空开关规则")
            fns.append(role)

        if ConvergeRole.objects.all():
            role = _with_role(ConvergeRole.objects.all()[0], switch=False)
            role.__name__ = 'remove_converge_role'
            role.short_description = ugettext_lazy(u"清空聚合规则")
            fns.append(role)

        actions = [ self.get_action(fn) for fn in fns ]
        actions = OrderedDict(
            (name, (func, name, desc))
            for func, name, desc in actions
        )
        return actions

这样每次刷新页面get_actions都会执行一遍, 做到动态actions.

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Django 进阶学习 - 动态actions
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档