Django: access the parent instance from the Inline model admin

后端 未结 3 1617
独厮守ぢ
独厮守ぢ 2020-12-14 03:33

How can I access the parent instance from the inline model admin?

My goal is to override the has_add_permission function based on the status of the pare

相关标签:
3条回答
  • 2020-12-14 03:36

    You only need to add obj parameter and check the parent model status

    class ChildInline(admin.TabularInline):
       model = Child
       form = ChildForm
    
       fields = (
        ...
        )
       extra = 0
       #You only need to add obj parameter 
       #obj is parent object now you can easily check parent object status
       def has_add_permission(self, request, obj=None):
            if obj.status == 1:
               return True
            else:
               return False
    
    
       class ParentAdmin(admin.ModelAdmin):
             inlines = [ChildInline,]
    
    0 讨论(0)
  • 2020-12-14 03:39

    I think this is a cleaner way to get the parent instance in the inline model.

    class ChildInline(admin.TabularInline):
        model = Child
        form = ChildForm
    
        fields = (...)
        extra = 0
    
        def get_formset(self, request, obj=None, **kwargs):
            self.parent_obj = obj
            return super(ChildInline, self).get_formset(request, obj, **kwargs)
    
        def has_add_permission(self, request):
            # Return True only if the parent has status == 1
            return self.parent_obj.status == 1
    
    
    class ParentAdmin(admin.ModelAdmin):
        inlines = [ChildInline, ]
    
    0 讨论(0)
  • 2020-12-14 03:54

    Django < 2.0 Answer:

    Use Django's Request object (which you have access to) to retrieve the request.path_info, then retrieve the PK from the args in the resolve match. Example:

    from django.contrib import admin
    from django.core.urlresolvers import resolve
    from app.models import YourParentModel, YourInlineModel
    
    
    class YourInlineModelInline(admin.StackedInline):
        model = YourInlineModel
    
        def get_parent_object_from_request(self, request):
            """
            Returns the parent object from the request or None.
    
            Note that this only works for Inlines, because the `parent_model`
            is not available in the regular admin.ModelAdmin as an attribute.
            """
            resolved = resolve(request.path_info)
            if resolved.args:
                return self.parent_model.objects.get(pk=resolved.args[0])
            return None
    
        def has_add_permission(self, request):
            parent = self.get_parent_object_from_request(request)
    
            # Validate that the parent status is active (1)
            if parent:
                return parent.status == 1
    
            # No parent - return original has_add_permission() check
            return super(YourInlineModelInline, self).has_add_permission(request)
    
    
    @admin.register(YourParentModel)
    class YourParentModelAdmin(admin.ModelAdmin):
        inlines = [YourInlineModelInline]
    

    Django >= 2.0 Answer:

    Credit to Mark Chackerian for the below update:

    Use Django's Request object (which you have access to) to retrieve the request.path_info, then retrieve the PK from the args in the resolve match. Example:

    from django.contrib import admin
    from django.urls import resolve
    from app.models import YourParentModel, YourInlineModel
    
    
    class YourInlineModelInline(admin.StackedInline):
        model = YourInlineModel
    
        def get_parent_object_from_request(self, request):
            """
            Returns the parent object from the request or None.
    
            Note that this only works for Inlines, because the `parent_model`
            is not available in the regular admin.ModelAdmin as an attribute.
            """
            resolved = resolve(request.path_info)
            if resolved.args:
                return self.parent_model.objects.get(pk=resolved.args[0])
            return None
    
        def has_add_permission(self, request):
            parent = self.get_parent_object_from_request(request)
    
            # Validate that the parent status is active (1)
            if parent:
                return parent.status == 1
    
            # No parent - return original has_add_permission() check
            return super(YourInlineModelInline, self).has_add_permission(request)
    
    
    @admin.register(YourParentModel)
    class YourParentModelAdmin(admin.ModelAdmin):
        inlines = [YourInlineModelInline]
    
    0 讨论(0)
提交回复
热议问题