1

から拡張した多くのモデルがありfeincms.models.Base、管理サイトで FeinCMS アイテム エディターを使用します (つまり、それらはすべて として使用feincms.admin.item_editor.ItemEditorしますModelAdmin)。

ModelAdminモデルには、モデルごとに拡張できる 共有クラスで定義できる共有機能がいくつかあります。

問題は、これは拡張機能ではうまく機能せずFeinCMS、拡張機能がModelAdmins に複数回追加するタブの重複など、予期しない結果を引き起こすことです。

拡張機能を台無しにせずにこれを行う方法はありますか?

4

1 に答える 1

1

これは可能ですが、少し異なる構文を採用する必要があります。まず、説明です。

ModelAdmins の単純な継承が壊れている理由は、FeinCMS 拡張機能がModelAdminクラスを操作する方法に関する 2 つの問題のためです。

  1. ModelAdminまず、 (例: )に添付されたリストまたは辞書SharedModelAdmin.list_displayは参照によって渡されるため、複数の ModelAdmin 間で共有されます。これは、拡張機能が同じリストに対して操作を 2 回実行することになる可能性があることを意味します (別の にアタッチされていてもModelAdmin)。
  2. 私たちではの設定をクラスadmin.pyレベルで定義しますが、FeinCMS は ModelAdmin のインスタンスを操作します。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']
于 2015-08-17T09:19:47.030 に答える