2010-06-27 98 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