На момент коммита e091c18f50266097f648efc7cac2503968e9d217 в четверг 14 августа 23:44:46 2012 +0200 принятое решение больше не может работать.
Текущая версия функции django.forms.models.modelform_factory () использует «метод конструирования типа», вызывая функцию type () в переданной форме, чтобы получить тип метакласса, а затем используя результат для построения класса. объект своего типа на лету ::
# Instatiate type(form) in order to use the same metaclass as form.
return type(form)(class_name, (form,), form_class_attrs)
Это означает, что даже объект curry
ed или partial
, переданный вместо формы, «заставляет утку вас укусить», так сказать: он вызовет функцию с параметрами конструкции объекта ModelFormClass
, возвращая сообщение об ошибке ::
function() argument 1 must be code, not str
Чтобы обойти эту проблему, я написал функцию генератора, которая использует замыкание для возврата подкласса любого класса, указанного в качестве первого параметра, который затем вызывает super.__init__
после update
обработки kwargs с теми, которые поставлены в вызове функции генератора ::
def class_gen_with_kwarg(cls, **additionalkwargs):
"""class generator for subclasses with additional 'stored' parameters (in a closure)
This is required to use a formset_factory with a form that need additional
initialization parameters (see /420620/django-peredacha-polzovatelskih-parametrov-formy-v-formset)
"""
class ClassWithKwargs(cls):
def __init__(self, *args, **kwargs):
kwargs.update(additionalkwargs)
super(ClassWithKwargs, self).__init__(*args, **kwargs)
return ClassWithKwargs
Тогда в вашем коде вы будете называть фабрику форм как ::
MyFormSet = inlineformset_factory(ParentModel, Model,form = class_gen_with_kwarg(MyForm, user=self.request.user))
предостережения:
- это получило очень мало испытаний, по крайней мере сейчас
- предоставленные параметры могут конфликтовать и перезаписывать те, которые используются любым кодом, который будет использовать объект, возвращаемый конструктором