10

MainModelとという名前のモデルが与えられた場合、後者RelatedModelには へのForeignKeyフィールドがありMainModelます。

class MainModel(models.Model):
    name = models.CharField(max_length=50)
    type = models.BooleanField()

class RelatedModel1(models.Model):
    main = models.ForeingKey(MainModel):
    name = models.CharField(max_length=50)

class RelatedModel2(models.Model):
    main = models.ForeingKey(MainModel):
    name = models.CharField(max_length=50)

および対応する ModelAdmin クラス:

class RelatedModel1InlineAdmin(admin.TabularInline):
    model = RelatedModel1

class RelatedModel2InlineAdmin(admin.TabularInline):
    model = RelatedModel2

class MainModel(admin.ModelAdmin):
    inlines = [RelatedModel1, RelatedModel2]

これがデフォルトの動作です。関連するモデルごとに 1 つずつ、合計 2 つのインラインを取得します。MainModel問題は、インスタンスが作成されているときにすべてのインラインを完全に非表示にする方法(ModelAdminadd_view)、およびインスタンスのフィールドが であるRelatedModel1ときにインラインを表示し、 whenでインラインを表示する方法です。typeMainModelTrueRelatedModel2False

属性の記述子を作成しようとしましたModelAdmin.inline_instancesが、編集中のオブジェクト インスタンスにアクセスする必要があることに気付きましたが、それはパラメーターとして渡されます。

何か助けはありますか?

ありがとう!

4

6 に答える 6

4

@Yuji 'Tomita' Tomitayou アイデアはよかっself.inlinesたです。したがって、インライン処理をメソッドに移動しました。change_viewadd_viewself.get_inline_instances(request)get_formsets()get_form()

これが私が成功した方法です:

class SampleAdmin(ModelAdmin):
    inlines = []

    def get_inlines(self):
        return [SampleInline, SampleInline2]

    def get_form(self, request, obj=None, **kwargs):
        # due to django admin form fields caching you must 
        # redefine inlines on every `get_form()` call
        if (obj): self.inlines = self.get_inlines()
        for inline in self.inlines:
            # Here change condition based on your needs and manipulate
            # self.inlines as you like (remove, change, etc). 
            # I used inline.__name__ to detect if this is correct inline 
            # for my obj
            if obj.CONDITION:
                self.inlines.remove(inline)
        return super(SampleAdmin, self).get_form(request, obj, **kwargs)
于 2013-01-29T16:04:31.217 に答える
2

change_viewModelAdmin でオーバーライドするだけです。

def change_view(self, request, object_id, form_url='', extra_context=None):
    obj = self.model.objects.filter(pk=object_id).first()
    if not obj:
        self.inlines = []
    else:
        if obj.type is True:
            self.inlines = [RelatedModel1InlineAdmin]
        else:
            self.inlines = [RelatedModel2InlineAdmin]

    return super().change_view(request,object_id,form_url=form_url,extra_context=extra_context)

それは私の仕事です。

于 2020-12-21T03:29:09.367 に答える
1

のぞき見からcontrib.admin.options.pyオーバーライドできるようですModelAdmin.get_formsets。管理サイトは に入力self.inline_instancesされることに注意してください。その__init__ため、インラインを何度もインスタンス化するのではなく、フォローすることをお勧めします。私はそれがどれほど高価なのか分かりません:)

def get_formsets(self, request, obj=None):
    if not obj:
        return [] # no inlines

    elif obj.type == True:
        return [MyInline1(self.model, self.admin_site).get_formset(request, obj)]

    elif obj.type == False:
        return [MyInline2(self.model, self.admin_site).get_formset(request, obj)]

    # again, not sure how expensive MyInline(self.model, self.admin_site) is. 
    # the admin does this once. You could instantiate them and store them on the 
    # admin class somewhere to reference instead.

元の管理者get_formsetsはジェネレーターを使用しています。元の管理者をより厳密に模倣することもできます。

def get_formsets(self, request, obj=None):
    for inline in self.inline_instances:
        yield inline.get_formset(request, obj)
于 2011-11-10T10:27:17.627 に答える
0

これは、同じ問題に直面したときに書いたコードです。少し強引なスタイルだと思いますが、非常に機敏で、あらゆる場合に適しているはずです。

class MyModelAdmin(admin.ModelAdmin):
    def __init__(self, *args, **kwargs):
        super(MyModelAdmin, self).__init__(*args, **kwargs)
        self.inline_instances_hash = {}
        for inline_class in self.inlines:
            for inline_instance in self.inline_instances:
                if isinstance(inline_instance, inline_class):
                    break
            self.inline_instances_hash[inline_class] = inline_instance

    def get_inline_instance(self, inline_class):
        return self.inline_instances_hash[inline_class]

    def get_form(self, request, obj=None, **kwargs):
        if obj:
            self.inline_instances = []
            if self.CONDITION:
                self.inline_instances.append(self.get_inline_instance(
                    THE_INLINE_CLASS_I_WANT))
            #...
        else:
            self.inline_instances = self.inline_instances_hash.values()
于 2014-04-07T11:51:13.277 に答える