[英]How can I subclass my ModelAdmins in a Django FeinCMS project?
I have a number of models that extend from feincms.models.Base
, and use the FeinCMS item editor in the admin site (ie they all use feincms.admin.item_editor.ItemEditor
as their ModelAdmin
). 我有许多模型从feincms.models.Base
扩展,并在管理站点中使用FeinCMS项目编辑器(即它们都使用feincms.admin.item_editor.ItemEditor
作为其ModelAdmin
)。
The models have some shared functionality that I want to be able to define in a shared ModelAdmin
class that I can then extend for each model. 这些模型具有一些共享功能,我希望能够在共享的ModelAdmin
类中定义这些函数,然后可以为每个模型扩展它们。
The problem is, this doesn't play well with FeinCMS
extensions, causing unexpected results, such as duplicate tabs, where the extensions add things to the ModelAdmin
s more than once. 问题是,这在FeinCMS
扩展中无法很好地发挥作用,从而导致意外结果,例如重复的选项卡,其中扩展ModelAdmin
将事物添加到ModelAdmin
。
Is there a way to do this without messing up the extensions? 有没有办法做到不弄乱扩展名呢?
This is possible, but you have to adopt slightly different syntax. 这是可能的,但是您必须采用稍微不同的语法。 First, an explanation. 首先,进行说明。
The reason that straightforward inheritance of ModelAdmins is broken is because of the two issues with the way FeinCMS extensions manipulate the ModelAdmin
classes: 打破对ModelAdmins的直接继承的原因是由于FeinCMS扩展操作ModelAdmin
类的方式存在两个问题:
ModelAdmin
(eg SharedModelAdmin.list_display
) are passed by reference, and so shared between multiple ModelAdmins. 首先,附加到ModelAdmin
任何列表或词典(例如SharedModelAdmin.list_display
)都通过引用传递,并因此在多个ModelAdmins之间共享。 This means that the extensions can end up performing an operation twice on the same list (even though it's attached to a different ModelAdmin
). 这意味着这些扩展最终可以在同一列表上执行两次操作(即使它已附加到不同的ModelAdmin
)。 admin.py
we define the ModelAdmin
's settings at the class level, FeinCMS manipulates the ModelAdmin's instance . 在admin.py
我们在类级别定义ModelAdmin
的设置,而FeinCMS则操作ModelAdmin的实例 。 So, in order to get it working, we can use the following mixin: 因此,为了使其正常工作,我们可以使用以下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()
Usage: 用法:
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.