Conditional string in Django admin?

I am trying to figure out a way to display the next 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 could find was that I could override get_formset, but I could not find a good example, so my weak attempt did not work.

Here is my unsuccessful 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 the inline string is not displayed regardless of whether Person.is_member is True or False.


Update: A friend suggested I try:

 inlines = [RelativeInline,] 

in

 self.inlines = [RelativeInline,] 

but to no avail. I also tried:

 PersonAdmin.inlines = [RelativeInline,] 

but the result was the same - no error, no built-in.

+7
django conditional django-admin inline
source share
3 answers

I decided to change the whole paradigm and solve my problem differently. Instead of having a separate administrator for all individuals with conditional inline, I decided:

  • Override the filtering query set for members only and save the RelativeInline with the administrator for this model.
  • Create a proxy model and redefine its request for filtering for non-members. The administrator for this model does not include RelativeInline.

In the end, I think this is a cleaner approach. Now members can be supported, and relatives (non-members) can be added to the line. NonMemberAdmin allows you to edit 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) 
+1
source share

Your original solution was pretty close. If you look in django / contrib / admin / options.py around line 290, you will see that the built-in classes are created when the model is instantiated, after which the inlines list inlines ignored. Therefore setting this list later in get_formsets () has no effect.

However, you are correct that get_formsets () is what you need to override to make your lines strong. Inline instances are contained in self.inline_instances , so to disable them based on an object (for example, I want to hide a specific line in the "add" form), you would redefine it like this:

 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) 
+3
source share

I understand this question is a bit old, and the code base has changed a bit; there is a cleaner point to redefine things now: get_inline_instances . You can do it:

 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 
0
source share

All Articles