This demonstrates creating a mixin for inlines along with a custom ModelAdmin to inject the instance into the inline for further processing.
One use case is for when you need to override get_field_queryset to filter available options in a dropdown field to limit selection to only those items associated with the parent.
class InstanceAwareInlineMixin(object):
"""
Create a mixin that supports setting an instance.
"""
def __init__(self, *args, **kwargs):
self.instance = None
super().__init__(*args, **kwargs)
def set_instance(self, instance):
self.instance = instance
class ModelAdmin(admin.ModelAdmin):
"""
Create a custom ModelAdmin that sets the instance on any inlines implementing the mixin
"""
def get_inline_instances(self, request, obj):
instances = super().get_inline_instances(request, obj=obj)
for i in instances:
if isinstance(i, InstanceAwareInlineMixin):
i.set_instance(obj)
return instances
class MyInline(InstanceAwareInlineMixin, admin.TabularInline):
"""
Implement a tabular inline that uses the mixin
"""
model = RelatedModel
fields = ('title', 'description')
def get_field_queryset(self, db, db_field, request):
if db_field.name == 'yet_another_model':
# Here we can access self.instance that was injected by the custom ModelAdmin
return YetAnotherModel.objects.filter(primary_model=self.instance)
return super().get_field_queryset(db, db_field, request)
# Remember to use the custom class here, not admin.ModelAdmin
class MyModelAdmin(ModelAdmin):
# ...