在Django管理员中使条件成为有条件的

Jas*_*ein 12 django conditional django-admin inlines

我有一个模型,我希望工作人员能够编辑事件的日期.像这样:

class ThingAdmin(admin.ModelAdmin):
    model = Thing

    if obj.date < today: #Something like that
        inlines = [MyInline,]
Run Code Online (Sandbox Code Playgroud)

问题是,我没有访问此级别的obj实例.我已经尝试重写get_formset(),但没有得到任何结果.

请指教?

Yuj*_*ita 10

感谢对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)
Run Code Online (Sandbox Code Playgroud)

  • 似乎Cerin的评论已过时,因为此答案已修改为使用get_inline_instances (2认同)

Chr*_*ard 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)
Run Code Online (Sandbox Code Playgroud)

我发布这个新答案是因为截至 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
Run Code Online (Sandbox Code Playgroud)


Avi*_*nna 7

您可以使用(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 []
Run Code Online (Sandbox Code Playgroud)

更新: 通过这种方法我遇到了这个问题,因此可以通过覆盖方法来完成相同的操作,而不是使用上述方法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 # ... the error msg
        else:
            if obj.date < today:
                self.inlines = [ThingInline,]

        return super(ThingAdmin, self).change_view(request, object_id, form_url, extra_context)
Run Code Online (Sandbox Code Playgroud)