Django:从Inline模型管理员访问父实例

Mic*_*ael 14 django django-forms django-admin

如何从内联模型管理员访问父实例?

我的目标是has_add_permission根据父实例的状态覆盖该功能.如果父级的状态不是1,我不想允许添加子级.

class ChildInline(admin.TabularInline):
    model = Child
    form = ChildForm

    fields = (
        ...
    )
    extra = 0

    def has_add_permission(self, request):
        # Return True only if the parent has status == 1
        # How to get to the parent instance?
        #return True

class ParentAdmin(admin.ModelAdmin):
    inlines = [ChildInline,]
Run Code Online (Sandbox Code Playgroud)

Mic*_*l B 18

Django <2.0答案:

使用Django的Request对象(您有权访问)来检索request.path_info,然后从resolve匹配中的args中检索PK .例:

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]
Run Code Online (Sandbox Code Playgroud)

Django> = 2.0答案:

感谢马克Chackerian为以下更新:

使用Django的Request对象(您有权访问)来检索request.path_info,然后从resolve匹配中的args中检索PK .例:

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]
Run Code Online (Sandbox Code Playgroud)

  • 我为python 3更改了一些内容.1)解析导入是`来自django.urls import resolve` 2)"已解决"逻辑是`如果已解决.kwargs.get('object_id'):return self.parent_model.objects. get(pk = resolved.kwargs ['object_id'])`. (5认同)

Ric*_*ina 10

我认为这是一种在内联模型中获取父实例的更简洁方法.

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, ]
Run Code Online (Sandbox Code Playgroud)


小智 6

我尝试了 Michael B 的解决方案,但对我不起作用,我不得不使用它(使用 kwargs 的一个小修改):

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.kwargs:
            return self.parent_model.objects.get(pk=resolved.kwargs["object_id"])
        return None
Run Code Online (Sandbox Code Playgroud)