Skip to content

Instantly share code, notes, and snippets.

@ihadgraft
Created October 20, 2021 11:03
Show Gist options
  • Save ihadgraft/1997c2ba8374c99cf43b0c3d4f17b555 to your computer and use it in GitHub Desktop.
Save ihadgraft/1997c2ba8374c99cf43b0c3d4f17b555 to your computer and use it in GitHub Desktop.
Strategy for passing a model instance from a ModelAdmin to an Inline

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):
    # ...
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment