繁体   English   中英

如何在Django FeinCMS项目中将ModelAdmins子类化?

[英]How can I subclass my ModelAdmins in a Django FeinCMS project?

我有许多模型从feincms.models.Base扩展,并在管理站点中使用FeinCMS项目编辑器(即它们都使用feincms.admin.item_editor.ItemEditor作为其ModelAdmin )。

这些模型具有一些共享功能,我希望能够在共享的ModelAdmin类中定义这些函数,然后可以为每个模型扩展它们。

问题是,这在FeinCMS扩展中无法很好地发挥作用,从而导致意外结果,例如重复的选项卡,其中扩展ModelAdmin将事物添加到ModelAdmin

有没有办法做到不弄乱扩展名呢?

这是可能的,但是您必须采用稍微不同的语法。 首先,进行说明。

打破对ModelAdmins的直接继承的原因是由于FeinCMS扩展操作ModelAdmin类的方式存在两个问题:

  1. 首先,附加到ModelAdmin任何列表或词典(例如SharedModelAdmin.list_display )都通过引用传递,并因此在多个ModelAdmins之间共享。 这意味着这些扩展最终可以在同一列表上执行两次操作(即使它已附加到不同的ModelAdmin )。
  2. admin.py我们在级别定义ModelAdmin的设置,而FeinCMS则操作ModelAdmin的实例

因此,为了使其正常工作,我们可以使用以下mixin:

class Faked(object):
    "A fake class to use to stand in for True in ExtendableModelAdminMixin."
    pass


class ExtendableModelAdminMixin(object):
    """ModelAdmin mixin to allow ModelAdmins to be extended (i.e.
subclassed) without messing
    up the Feincms extension registering mechanism.

    Technical note: the reason we do this is because otherwise references
    get preserved across different ModelAdmins, which means the ModelAdmins
    fail Django's checks.
    The straightforward declarative syntax of ModelAdmins sets
    attributes at the class level, but FeinCMS's
    initialize_extensions() method overrides them on the
    instance level.  So in our mixin we do a deepcopy of any
    instance level attributes before initializing the extensions.
    """
    def __init__(self, *args, **kwargs):
        # Set the _extensions_initialized attribute to prevent
        # extensions being initialized just yet
        self._extensions_initialized = Faked
        super(ExtendableModelAdminMixin, self).__init__(*args, **kwargs)

        # Before running extensions, copy any lists so we don't
        # preserve references across different ModelAdmin subclasses
        # TODO - include any other ModelAdmin properties that
        # are causing issues.
        for attr_name in ('list_display',
                          'fieldsets',
                          'search_fields', 'list_filter'):
            original = getattr(self, attr_name, [])
            copied_attr = deepcopy(original)
            setattr(self, attr_name, copied_attr)

        # Now we're ready to initialize extensions
        del(self._extensions_initialized)
        self.initialize_extensions()

用法:

class SharedModelAdmin(ExtendableModelAdmin, ItemEditor):
    # Declare some defaults here, as usual
    list_display = ['field_one', 'field_two']

class MyModelAdmin(SharedModelAdmin):
    def __init__(self, *args, **kwargs):
        super(MyModelAdmin, self).__init__(*args, **kwargs)
        # Override things at the instance level
        self.list_display += ['field_three']

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM