我有许多从feincms.models.Base
扩展的模型,并在管理站点中使用FeinCMS项目编辑器(即它们都使用feincms.admin.item_editor.ItemEditor
作为其ModelAdmin
)。
这些模型具有一些共享功能,我希望能够在共享的ModelAdmin
类中定义这些功能,然后可以为每个模型扩展这些功能。
问题是,这在FeinCMS
扩展名中无法正常使用,导致
意外的结果,例如重复的选项卡,其中扩展将内容多次添加到ModelAdmin
。
有没有办法做到不弄乱扩展名呢?
最佳答案
这是可能的,但是您必须采用稍微不同的语法。首先,进行说明。
破坏了ModelAdmins的直接继承的原因是由于FeinCMS扩展操作ModelAdmin
类的两个问题:
首先,附加到ModelAdmin
(例如SharedModelAdmin.list_display
)的任何列表或词典都是通过引用传递的,因此在多个ModelAdmins之间共享。这意味着扩展可以最终在同一列表上执行两次操作(即使它附加到了不同的ModelAdmin
上)。
在我们的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']
关于python - 如何在Django FeinCMS项目中将ModelAdmins子类化?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/32046741/