14

イベントの日付までスタッフが編集できるようにしたいモデルがあります。このような:

class ThingAdmin(admin.ModelAdmin):
    model = Thing

    if obj.date < today: #Something like that
        inlines = [MyInline,]

問題は、このレベルではobjインスタンスにアクセスできないことです。get_formset()をオーバーライドしようとしましたが、どこにも到達しませんでした。

お知らせ下さい?

4

9 に答える 9

11

1.4での変更に対するコメントに感謝します。ここでの私の実装もスレッドセーフではなかったので、実際には削除する必要がありました。

get_formsetsオブジェクトが渡されてが呼び出されるためget_inline_instances、オブジェクトに作用するように両方の関数を変更できます。

これは機能するはずです:

class ThingAdmin(admin.ModelAdmin):
    model = Thing

    inlines = [inline]
    other_set_of_inlines = [other_inline]

    def get_inline_instances(self, request, obj=None):
        #                                    ^^^ this is new
        inline_instances = []

        if obj.date > datetime.date(2012, 1, 1):
            inlines = self.inlines
        else:
            inlines = self.other_set_of_inlines

        for inline_class in inlines:
            inline = inline_class(self.model, self.admin_site)
            if request:
                if not (inline.has_add_permission(request) or
                        inline.has_change_permission(request) or
                        inline.has_delete_permission(request)):
                    continue
                if not inline.has_add_permission(request):
                    inline.max_num = 0
            inline_instances.append(inline)
        return inline_instances

    def get_formsets(self, request, obj=None):
        for inline in self.get_inline_instances(request, obj):
            #                                           ^^^^^ this is new
            yield inline.get_formset(request, obj)
于 2011-03-23T22:08:44.787 に答える
8

Django 2.2.2(この記事の執筆時点での現在の最新バージョン)の時点で、@ aggieNick02によって以前に提供されたソリューションを使用します。これは、get_inline_instances以下に示すオーバーライドです。

class ThingAdmin(models.ModelAdmin):
    inlines = [MyInline,]

    def get_inline_instances(self, request, obj=None):
        if not obj or obj.date >= today: return []
        return super(ThingAdmin, self).get_inline_instances(request, obj)

2019年4月17日の時点で、このコミットでこの新しい回答を投稿しています。これを行うための将来の推奨方法は、代わりにメソッドをオーバーライドすることであるようget_inlinesです。したがって、それ以降のバージョンでは、これに対する解決策は次のコードのようになります。これにより、さまざまなインラインセットを指定し、条件に基づいてそれらを使用できます。

class ThingAdmin(admin.ModelAdmin):
    model = Thing

    inlines = [inline]
    other_set_of_inlines = [other_inline]

    def get_inlines(self, request, obj):
        if obj.date > datetime.date(2012, 1, 1):
            return self.inlines
        else:
            return self.other_set_of_inlines
于 2019-06-20T16:25:09.080 に答える
6

django 3.0+ )get_inlinesメソッドを使用できます。メソッドをオーバーライドしてロジックを定義するだけです。

class ThingInline(admin.StackedInline):
    """ inline needs to be returned """
    models = ThingModel


class ThingAdmin(admin.ModelAdmin):
    model = Thing
    inlines = []

    def get_inlines(self, request, obj):
        if obj.date < today:    # the date
            return [ThingInline]
        # or else
        return []

更新: このアプローチを経て、私はこの問題に直面したので、上記のアプローチを使用する代わりに、同じことを過剰change_view()な方法で行うことができます、

class ThingAdmin(admin.ModelAdmin):
    model = Thing
    inlines = []

    def change_view(self, request, object_id, form_url='', extra_context=None):
        self.inlines = []
    
        try:
            obj = self.model.objects.get(pk=object_id)
        except self.model.DoesNotExist:
            pass
        else:
            if obj.date < today:
                self.inlines = [ThingInline,]

        return super(ThingAdmin, self).change_view(request, object_id, form_url, extra_context)
于 2021-03-17T08:45:40.560 に答える
4

試したソリューションが予期しない方法で失敗するという複雑なケースがありました(インラインの読み取り専用フィールドの問題)。これは私が見つけた最も明確でフェイルセーフな方法です:

class MyAdmin(admin.ModelAdmin):

    def add_view(self, request, form_url='', extra_context=None):
        self.inlines = [InlineA, InlineC]
        return super(MyAdmin, self).add_view(request, form_url, extra_context)

    def change_view(self, request, object_id, form_url='', extra_context=None):
        self.inlines = [InlineB, InlineC, InlineD]
        return super(MyAdmin, self).change_view(request, object_id, form_url, extra_context)

これはDjango1.4.xで機能しています。

于 2013-07-25T21:08:29.117 に答える
2

Djangoの最近のバージョンでは、ModelAdmin.get_formsetsをオーバーライドする必要があります。例えば

class MyAdmin(admin.ModelAdmin):

    def get_formsets(self, request, obj=None):
        if obj:
            for _ in super(MyAdmin, self).get_formsets(request, obj):
                yield _
        else:
            for inline in self.get_specific_inlines(request):
                yield inline.get_formset(request, obj)
于 2013-02-12T22:14:53.510 に答える
0

特定のストーリーでアクセスしていた管理サイトに基づいてインラインを表示する必要がある状況がありました。

次のコードを使用して、Django1.3で動的インラインを機能させることができました。

ハイライト/admin.pyで

class HighlightInline(generic.GenericTabularInline):
    model = Highlight
    extra = 1
    max_num = 4
    fields = ('order', 'highlight')
    template = 'admin/highlights/inline.html'

class HighlightAdmin(admin.ModelAdmin):
    def regulate_highlight_inlines(self):
        highlights_enabled = Setting.objects.get_or_default('highlights_enabled', default='')
        highlight_inline_instance = HighlightInline(self.model, self.admin_site)
        highlight_found = any(isinstance(x, HighlightInline) for x in self.inline_instances)
        if highlights_enabled.strip().lower() == 'true':
            if not highlight_found:
                self.inline_instances.insert(0, highlight_inline_instance)
        else:
            if highlight_found:
                self.inline_instances.pop(0)
        print self.inline_instances

    def change_view(self, request, object_id, form_url='', extra_context=None):
        self.regulate_highlight_inlines()
        return super(HighlightAdmin, self).change_view(request, object_id)

    def add_view(self, request, form_url='', extra_context=None):
        self.regulate_highlight_inlines()   
        return super(HighlightAdmin, self).add_view(request, form_url, extra_context)

story/admin.pyで

class StoryAdmin(HighlightAdmin):

注意すべき点の1つは、インラインクラス(HighlightInline)を操作しているだけでなく、インラインインスタンス(HighlightInline(self.model、self.admin_site))を変更していることです。これは、管理クラスの初期構築時に、djangoがインラインクラスのリストに基づいてインラインインスタンスのリストをすでに構築しているためです。

于 2014-06-15T14:30:43.623 に答える
0

これをハックする最も簡単な方法は、カスタム関数を設定するだけでget_fields、などでカスタム関数を呼び出すことだと思います。get_fieldsetsself.inlines

class XXXAdmin(admin.ModelAdmin):
    def set_inlines(self, request, obj):
        """ hack inlines models according current request.user or obj """
        self.inlines = []
        if request.user.is_superuser or request.user is obj.recorder:
            self.inlines = [AbcInline, ]

    def get_fields(self, request, obj=None):
        self.set_inlines(request, obj)  # NOTICE this line
        super(XXXAdmin, self).get_fields(request, obj)
于 2017-01-16T07:04:13.363 に答える
0

これを行う最も簡単な方法は、get_inline_instancesをオーバーライドしてスーパーコールすることです。

class ThingAdmin(models.ModelAdmin):
    inlines = [MyInline,]

    def get_inline_instances(self, request, obj=None):
        unfiltered = super(ThingAdmin, self).get_inline_instances(request, obj)
        #filter out the Inlines you don't want
        keep_myinline = obj and obj.date < today
        return [x for x in unfiltered if not isinstance(x,MyInline) or keep_myinline]

これにより、MyInlineは必要なときに配置され、不要なときに配置されます。クラスにある唯一のインラインがMyInlineであることがわかっている場合は、それをさらに簡単にすることができます。

class ThingAdmin(models.ModelAdmin):
    inlines = [MyInline,]

    def get_inline_instances(self, request, obj=None):
        if not obj or obj.date >= today:
            return []
        return super(ThingAdmin, self).get_inline_instances(request, obj)
于 2017-10-17T16:00:42.500 に答える
0

この問題の最善の解決策は、すでにここで回答されています。get_inline_instancesオーバーライドchange_viewメソッドをオーバーライドする代わりに。

def change_view(self, request, object_id, form_url='', extra_context=None):
    self.inlines = []
    try:
        obj = self.model.objects.get(pk=object_id)
    except self.model.DoesNotExist:
        pass
    else:
        if condition:
            self.inlines = [InlineClass]
    return super(AdminClass, self).change_view(request, object_id, form_url, extra_context)
于 2021-10-10T19:11:57.467 に答える