Python 如何从Django中的inlineadmin获取当前模型实例

Python 如何从Django中的inlineadmin获取当前模型实例,python,django,django-admin,Python,Django,Django Admin,我正在使用中给出的许多表单字段。 但在该函数中,我需要获取正在编辑的当前父对象 def formfield_for_manytomany(self, db_field, request, **kwargs): if db_field.name == "car": kwargs["queryset"] = Cars.objects.filter(owner=person) return super(myModel, self).formfield_for_manyt

我正在使用中给出的许多表单字段。 但在该函数中,我需要获取正在编辑的当前父对象

def formfield_for_manytomany(self, db_field, request, **kwargs):
    if db_field.name == "car":
        kwargs["queryset"] = Cars.objects.filter(owner=person)
    return super(myModel, self).formfield_for_manytomany(db_field, request, **kwargs)

如何获取正在编辑的人员?

如果无法从
请求
轻松获取
人员
,您可能需要通过覆盖
ModelAdmin.get\u form()
InlineModelAdmin.get\u formset()
手动传递该人员:


为了访问InlineModelAdmin的父ModelAdmin的模型实例,我在过去使用过以下方法:

class PersonAdmin(ModelAdmin):
    def get_formsets(self, request, obj=None, *args, **kwargs):
        for inline in self.inline_instances:
            inline._parent_instance = obj
            yield inline.get_formset(request, obj)

class CarInline(TabularInline):
    _parent_instance = None

    def get_formset(self, *args, **kwargs):
        def formfield_callback(field, **kwargs):
            formfield = field.formfield(**kwargs)
            if field.name == 'car':
                formfield.queryset = Cars.objects.filter(owner=self._parent_instance)
            return formfield

        if self._parent_instance is not None:
            kwargs['formfield_callback'] = formfield_callback
        return super(CarInline, self).get_formset(*args,
                                                                 **kwargs)

get\u formset()
/
get\u formset()
/
formfield\u for\u dbfield()
中,我发现了一种更干净的方法,不需要所有的黑客攻击。使用Django的请求对象(您可以访问该对象)检索PK,然后从匹配中的参数中检索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)
        if parent and parent.is_active is True:
            return False
        return super(YourInlineModelInline, self).has_add_permission(request)

    def get_formset(self, request, *args, **kwargs):
        """
        Using the get_formset example from above to override the QuerySet.
        """
        def formfield_callback(field, **kwargs):
            formfield = field.formfield(**kwargs)
            if field.name == 'car':
                formfield.queryset = self.parent_model.objects.filter(
                    owner=self.get_parent_object_from_request(request)
                )
            return formfield

        if self.get_parent_object_from_request(request) is not None:
            kwargs['formfield_callback'] = formfield_callback

        return super(YourInlineModelInline, self).get_formset(*args, **kwargs)


@admin.register(YourParentModel)
class YourParentModelAdmin(admin.ModelAdmin):
    inlines = [YourInlineModelInline]

我不明白。什么是
formfield\u回调
什么是
partial
回调是调用
formfield\u for u manytomy
的幕后魔法,我们需要手动将
obj
传递给它,以便从
kwargs
内部
formfield\u for u manytomy
中获取
obj
partial
部分生成了一个高阶函数,当被称为
formfield\u回调(一些参数)
时,它的行为就像
self.formfield\u for\u dbfield(请求,一些参数)
,您可以检查,一切都超出了我的理解。我有两个问题。从这里我可以得到更多关于
formfield\u回调的信息。这是django的内部版本还是它的定制版本2。我如何知道kwargs中可用的东西、字段或函数。我想你怎么知道obj在里面kwargs@user20822261.formfield_回调在Django中有点硬编码,不传递
obj
,但是我们可以很容易地定制它。2.
kwargs
由Django表单填充以生成表单字段,因此它可能包含字段接受的可能内容:
小部件
查询集
。在这里,我们确实混合了具有不同目标的参数,因此请记住将其命名为唯一(
obj
Here`)。我得到了这个错误
\uuuu init\uuuuu(),得到了一个意外的关键字参数obj
,没有足够的时间进行适当的编辑,因此我将在这里留下一些注释,以便在Django 2.0下完成此工作:
from Django.url import resolve
pk=resolved.kwargs['object\u id']
,对于ModelAdmin
self.parent\u model
->
self.model
我觉得这是更好、更简单的解决方案。我做了类似的操作,但没有使用resolve()函数。我只是做了一些类似于
object\u id=request.path.split(“/”[4]
的事情,知道id永远是请求URL中的第四个参数。
class PersonAdmin(ModelAdmin):
    def get_formsets(self, request, obj=None, *args, **kwargs):
        for inline in self.inline_instances:
            inline._parent_instance = obj
            yield inline.get_formset(request, obj)

class CarInline(TabularInline):
    _parent_instance = None

    def get_formset(self, *args, **kwargs):
        def formfield_callback(field, **kwargs):
            formfield = field.formfield(**kwargs)
            if field.name == 'car':
                formfield.queryset = Cars.objects.filter(owner=self._parent_instance)
            return formfield

        if self._parent_instance is not None:
            kwargs['formfield_callback'] = formfield_callback
        return super(CarInline, self).get_formset(*args,
                                                                 **kwargs)
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)
        if parent and parent.is_active is True:
            return False
        return super(YourInlineModelInline, self).has_add_permission(request)

    def get_formset(self, request, *args, **kwargs):
        """
        Using the get_formset example from above to override the QuerySet.
        """
        def formfield_callback(field, **kwargs):
            formfield = field.formfield(**kwargs)
            if field.name == 'car':
                formfield.queryset = self.parent_model.objects.filter(
                    owner=self.get_parent_object_from_request(request)
                )
            return formfield

        if self.get_parent_object_from_request(request) is not None:
            kwargs['formfield_callback'] = formfield_callback

        return super(YourInlineModelInline, self).get_formset(*args, **kwargs)


@admin.register(YourParentModel)
class YourParentModelAdmin(admin.ModelAdmin):
    inlines = [YourInlineModelInline]