How to show different inlines depending of current object field value
@Yuji 'Tomita' Tomitayou the idea was good, i had the same but once trying, i realized you must also remove specific key from self.inlines
because in change_view
and add_view
method self.get_inline_instances(request)
is called before get_formsets()
. Therefore i moved inlines handling to get_form()
method.
Here is how i sucessfully did it:
class SampleAdmin(ModelAdmin): inlines = [] def get_inlines(self): return [SampleInline, SampleInline2] def get_form(self, request, obj=None, **kwargs): # due to django admin form fields caching you must # redefine inlines on every `get_form()` call if (obj): self.inlines = self.get_inlines() for inline in self.inlines: # Here change condition based on your needs and manipulate # self.inlines as you like (remove, change, etc). # I used inline.__name__ to detect if this is correct inline # for my obj if obj.CONDITION: self.inlines.remove(inline) return super(SampleAdmin, self).get_form(request, obj, **kwargs)
I realize this question's a bit old and the codebase has changed a bit; there's a cleanish point to override things at now: get_inline_instances
. You can do this:
class MainModelAdmin(models.ModelAdmin): inlines = [RelatedModel1InlineAdmin,RelatedModel2InlineAdmin] def get_inline_instances(self, request, obj=None): #Return no inlines when obj is being created if not obj: return [] unfiltered = super(MainModelAdmin, self).get_inline_instances(request, obj) #filter out the Inlines you don't want if obj.type: return [x for x in unfiltered if isinstance(x,RelatedModel1InlineAdmin)] else: return [x for x in unfiltered if isinstance(x,RelatedModel2InlineAdmin)]
This worked for me while searching for an answer to the same problem in this old post.Expanding upon darklow's answer , I think you can simply override get_inline_instances
completely and add an extra check based on your type.
Add a boolean type check method in your model
class MainModel(models.Model): name = models.CharField(max_length=50) type = models.BooleanField() def is_type1(self): return type=="some value" def is_type2(self): return type=="some value"
Add inline instance base on type check - Simply copy and paste the get_inline_insances method from the parent class into your admin.ModelAdmin class and add the if block to check the model type as shown below
class MyModelAdmin(admin.ModelAdmin): inlines = [RelatedModel1, RelatedModel2] def get_inline_instances(self, request, obj=None): inline_instances = [] if not obj: return [] for inline_class in self.inlines: inline = inline_class(self.model, self.admin_site) if request: if not (inline.has_add_permission(request) or inline.has_change_permission(request, obj) or inline.has_delete_permission(request, obj)): continue if not inline.has_add_permission(request): inline.max_num = 0 if obj.is_type1() and isinstance(inline,RelatedModel1InlineAdmin): inline_instances.append(inline) if obj.is_type2() and isinstance(inline,RelatedModel2InlineAdmin): inline_instances.append(inline) return inline_instances