2010-06-27 97 views
7

我想弄清楚只有在Person.is_member为True时才显示以下RelativeInline的方法。在Django admin中有条件内联?

当前admin.py:

class RelativeInline(admin.TabularInline): 
    model = Relative 
    fk_name = 'member' 

class PersonAdmin(admin.ModelAdmin): 
    inlines = [RelativeInline,] 
    ordering = ('first_name',) 
    list_filter = ('is_member',) 
    search_fields = ('first_name', 'last_name',) 
    date_hierarchy = 'member_date' 
    list_display = ('first_name', 'last_name', 'is_member', 'member_date', 'photo') 

admin.site.register(Person, PersonAdmin) 

我已经能够找到的唯一的暗示是,我也许能覆盖get_formset,但我无法找到一个很好的例子,所以我的愚蠢的尝试没有工作。

这里是我的失败尝试:

class RelativeInline(admin.TabularInline): 
    model = Relative 
    fk_name = 'member' 

class PersonAdmin(admin.ModelAdmin): 
    ordering = ('first_name',) 
    list_filter = ('is_member',) 
    search_fields = ('first_name', 'last_name',) 
    date_hierarchy = 'member_date' 
    list_display = ('first_name', 'last_name', 'is_member', 'member_date', 'photo') 

    def get_formset(self, request, obj=None, **kwargs): 
     if obj.is_member: 
      inlines = [RelativeInline,] 
     return super(PersonAdmin, self).get_formset(request, obj, **kwargs) 

admin.site.register(Person, PersonAdmin) 

有没有这个代码产生的错误,但无论Person.is_member是否是真还是假没有内嵌出现。


更新: 一个朋友建议我尝试改变:

inlines = [RelativeInline,] 

到:

self.inlines = [RelativeInline,] 

,但无济于事。我也试过:

PersonAdmin.inlines = [RelativeInline,] 

但结果是一样的 - 没有错误,没有内联。

回答

1

我决定改变整个范例并以不同的方式解决我的问题。相反,具有用于与有条件内嵌所有的人在一个admin的,我决定:

  1. 覆盖的查询集来过滤成员只,并保持RelativeInline与管理这种模式
  2. 创建一个代理模型和重写它的查询集以筛选非成员。此模型的管理员不包含RelativeInline。

最后,我认为这是一个更清洁的方法。现在可以维护成员,并且可以在内联中添加亲属(非成员)。 NonMemberAdmin允许编辑非成员。

models.py:

class Person(models.Model): 
    first_name = models.CharField(max_length=50) 
    last_name = models.CharField(max_length=50) 
    is_member = models.BooleanField() 
    is_active = models.BooleanField(default=True) 

    class Meta: 
     verbose_name_plural = 'Members' 
     ordering = ('first_name', 'last_name') 

class PersonProxy(Person): 
    class Meta: 
     proxy = True 
     verbose_name_plural = 'Non-Members' 

class Relationship(models.Model): 
    name = models.CharField(max_length=50) 

class Relative(models.Model): 
    member = models.ForeignKey(Person, related_name='relative_member') 
    relative = models.ForeignKey(Person, related_name='relative_relative') 
    relationship = models.ForeignKey(Relationship) 

admin.py:

class RelativeInline(admin.TabularInline): 
    model = Relative 
    fk_name = 'member' 


class MemberAdmin(admin.ModelAdmin): 
    inlines = [RelativeInline,] 
    ordering = ('first_name',) 
    # list_filter = ('is_member',) 
    search_fields = ('first_name', 'last_name',) 
    # date_hierarchy = 'member_date' 
    list_display = ('first_name', 'last_name', 'member_date') 

    def queryset(self, request): 
     return (super(MemberAdmin, self).queryset(request) 
       .filter(is_member=True, is_active=True)) 


class NonMemberAdmin(admin.ModelAdmin): 
    ordering = ('first_name',) 
    search_fields = ('first_name', 'last_name',) 
    list_display = ('first_name', 'last_name') 

    def queryset(self, request): 
     return (super(NonMemberAdmin, self).queryset(request) 
       .filter(is_member=False, is_active=True)) 


admin.site.register(Person, MemberAdmin) 
admin.site.register(PersonProxy, NonMemberAdmin) 
3

你原来的解决方案是很接近。如果你看看290行左右的django/contrib/admin/options.py,你会发现当model admin被实例化时,内联类被实例化,之后inlines列表被忽略。因此,稍后在get_formsets()中设置此列表不起作用。

但是,您说的正确的是get_formsets()是为了使内联有条件而重写的。内联实例包含在self.inline_instances中,因此要基于对象(例如,对象)禁用它们。说我想隐藏的“附加”的形式在一个特定的内联),你会忽略它想:

class MyAdmin(models.ModelAdmin): 

    inlines = [MyInline, SomeOtherInline] 

    def get_formsets(self, request, obj=None): 
     for inline in self.inline_instances: 
      if isinstance(inline, MyInline) and obj is None: 
       continue 
      yield inline.get_formset(request, obj) 
+1

更新2014年的Django 1.6:在self.get_inline_instances '内联(请求,OBJ):' – imposeren 2014-10-10 11:29:09

0

我意识到这个问题是一个有点老的代码库已经改变了一点;现在有一个更清晰的要点:get_inline_instances。你可以这样做:

class PersonAdmin(models.ModelAdmin): 

inlines = [RelativeInline,] 

def get_inline_instances(self, request, obj=None): 
    to_return = super(MyAdmin, self).get_inline_instances(request, obj) 
    #filter out the RelativeInlines if obj.is_member is false 
    if not obj or not obj.is_member: 
     to_return = [x for x in to_return if not isinstance(x,RelativeInline)] 
    return to_return