views:

51

answers:

1

I'm trying to figure out a way to display the following RelativeInline only if Person.is_member is True.

Current 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)

The only hint I've been able to find is that I might be able to override get_formset, but I couldn't find a good example, so my feeble attempt didn't work.

Here's my failed attempt:

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)

There are no errors generated by this code, but no inline appears regardless of whether or not Person.is_member is True or False.


Update: A friend suggested I try changing:

inlines = [RelativeInline,]

to:

self.inlines = [RelativeInline,]

but to no avail. I also tried:

PersonAdmin.inlines = [RelativeInline,]

but the result was the same -- no error, no inline.

A: 

I decided to change the whole paradigm and solve my problem a different way. Instead of having a single admin for all Persons with a conditional inline, I decided to:

  1. Override the queryset to filter for members-only and keep RelativeInline with the admin for this model
  2. Create a proxy model and override its queryset to filter for non-members. The admin for this model does not include RelativeInline.

In the end, I think this is a cleaner approach. Now Members can be maintained, and relatives (non-members) can be added in the inline. The NonMemberAdmin allows for editing non-members.

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)
Tony Guinta