Django在内联表单管理中获取实例

Art*_*rti 8 django inline django-forms django-admin python-2.7

有一个内联表单类:

class ItemColorSelectForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        super(ItemColorSelectForm, self).__init__(*args, **kwargs)
        #here i need current object
Run Code Online (Sandbox Code Playgroud)

内联类:

class ItemColorSelectInline(generic.GenericTabularInline):
    model = ColorSelect
    extra = 1
    form = ItemColorSelectForm
Run Code Online (Sandbox Code Playgroud)

管理员班

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

问题:如何获取当前对象ItemColorSelectForm.

print kwargs 返回:

{'auto_id': u'id_%s', 'prefix': u'catalog-colorselect-content_type-object_id-__prefix__', 'empty_permitted': True}
Run Code Online (Sandbox Code Playgroud)

Elw*_*ens 6

目前接受的解决方案不是线程安全的.如果您关心线程安全,请永远不要将实例分配给静态类属性.

线程安全解决方案是:

对于Django 1.7 <1.9(可能是早期版本,不清楚):

from django.utils.functional import cached_property

def get_formset(self, *args, **kwargs):
    FormSet = super(InlineAdmin, self).get_formset(*args, **kwargs)

    class ProxyFormSet(FormSet):
        def __init__(self, *args, **kwargs):
            self.instance = kwargs['instance']
            super(ProxyFormSet, self).__init__(*args, **kwargs)

        @cached_property
        def forms(self):
            kwargs = {'instance': self.instance}
            forms = [self._construct_form(i, **kwargs) 
                    for i in xrange(self.total_form_count())]
            return forms
    return ProxyFormSet
Run Code Online (Sandbox Code Playgroud)

Django 1.9开始 > =也可以传递form_kwargs:

def get_formset(self, *args, **kwargs):
    FormSet = super(InlineAdmin, self).get_formset(*args, **kwargs)

    class ProxyFormSet(FormSet):
        def __init__(self, *args, **kwargs):
            form_kwargs = kwargs.pop('form_kwargs', {})
            form_kwargs['instance'] = kwargs['instance']
            super(ProxyFormSet, self).__init__(
                *args, form_kwargs=form_kwargs, **kwargs)
    return ProxyFormSet
Run Code Online (Sandbox Code Playgroud)

以上解决方案将以模型形式提供实例kwarg:

class InlineForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        super(InlineForm, self).__init__(*args, **kwargs)
        print('instance', kwargs['instance'])
Run Code Online (Sandbox Code Playgroud)


Art*_*rti 3

解决方案: 重写Inline类中的formset方法

def get_formset(self, request, obj=None, **kwargs):
        InlineForm.obj = obj
        return super(InlineAdmin, self).get_formset(request, obj, **kwargs)
Run Code Online (Sandbox Code Playgroud)