Это было исправлено в Django 1.9 с помощью form_kwargs .
У меня есть форма Django, которая выглядит так:
class ServiceForm(forms.Form):
option = forms.ModelChoiceField(queryset=ServiceOption.objects.none())
rate = forms.DecimalField(widget=custom_widgets.SmallField())
units = forms.IntegerField(min_value=1, widget=custom_widgets.SmallField())
def __init__(self, *args, **kwargs):
affiliate = kwargs.pop('affiliate')
super(ServiceForm, self).__init__(*args, **kwargs)
self.fields["option"].queryset = ServiceOption.objects.filter(affiliate=affiliate)
Я называю эту форму примерно так:
form = ServiceForm(affiliate=request.affiliate)
куда request.affiliate
находится вошедший в систему пользователь. Это работает как задумано.
Моя проблема в том, что теперь я хочу превратить эту единственную форму в набор форм. Что я не могу понять, так это как я могу передать информацию о партнере отдельным формам при создании набора форм. В соответствии с документами, чтобы сделать форму из этого, мне нужно сделать что-то вроде этого:
ServiceFormSet = forms.formsets.formset_factory(ServiceForm, extra=3)
И тогда мне нужно создать это так:
formset = ServiceFormSet()
Теперь, как я могу передать affiliate = request.affiliate отдельным формам таким образом?
источник
functools.partial
вместо Djangodjango.utils.functional.curry
. Они делают то же самое, за исключением того, чтоfunctools.partial
возвращает обычный вызываемый тип вместо обычной функции Python, и этотpartial
тип не привязывается как метод экземпляра, который аккуратно решает проблему, которую этот поток комментариев в основном посвятил отладке.Официальный документ Way
Джанго 2.0:
https://docs.djangoproject.com/en/2.0/topics/forms/formsets/#passing-custom-parameters-to-formset-forms
источник
Я бы динамически создал класс формы в функции, чтобы он имел доступ к филиалу через замыкание:
В качестве бонуса вам не нужно переписывать набор запросов в поле параметров. Недостатком является то, что подклассы немного прикольные. (Любой подкласс должен быть создан аналогичным образом.)
редактировать:
В ответ на комментарий вы можете вызывать эту функцию в любом месте, где бы вы использовали имя класса:
источник
Вот что сработало для меня, Джанго 1.7:
Надеюсь, это кому-нибудь поможет, мне понадобилось много времени, чтобы понять это;)
источник
staticmethod
здесь нужно?Мне нравится решение замыкания для того, чтобы быть «чище» и более Pythonic (так что +1 к ответу mmarshall), но формы Django также имеют механизм обратного вызова, который вы можете использовать для фильтрации наборов запросов в наборах форм.
Это также не задокументировано, что, по-моему, является показателем, который может не понравиться разработчикам Django.
Таким образом, вы в основном создаете свой набор форм так же, но добавляете обратный вызов:
Это создает экземпляр класса, который выглядит следующим образом:
Это должно дать вам общее представление. Немного сложнее сделать обратный вызов объектным методом, подобным этому, но он дает вам немного больше гибкости, чем простой вызов функции.
источник
Я хотел разместить это как комментарий к ответу Карла Мейерса, но так как это требует баллов, я просто разместил его здесь. Это заняло у меня 2 часа, поэтому я надеюсь, что это кому-нибудь поможет.
Примечание об использовании inlineformset_factory.
Я сам использовал это решение, и оно работало идеально, пока я не попробовал его с помощью inlineformset_factory. Я использовал Django 1.0.2 и получил какое-то странное исключение KeyError. Я обновил до последней версии багажника, и он работал напрямую.
Теперь я могу использовать его так:
источник
modelformset_factory
. Спасибо за этот ответ!На момент фиксации e091c18f50266097f648efc7cac2503968e9d217 в четверг 14 августа 23:44:46 2012 +0200 принятое решение больше не может работать.
Текущая версия функции django.forms.models.modelform_factory () использует «метод конструирования типа», вызывая функцию type () в переданной форме, чтобы получить тип метакласса, а затем используя результат для создания объекта класса своего тип на лету ::
Это означает, что даже
curry
ed илиpartial
объект, переданный вместо формы, «заставляет утку вас укусить», так сказать: он вызовет функцию с параметрами конструкцииModelFormClass
объекта, возвращая сообщение об ошибке:Чтобы обойти это, я написал функцию генератора, которая использует замыкание для возврата подкласса любого класса, указанного в качестве первого параметра, который затем вызывает
super.__init__
после вызоваupdate
kwargs с теми, которые указаны в вызове функции генератора:Затем в своем коде вы будете называть фабрику форм как:
предостережения:
источник
Решение Карла Мейера выглядит очень элегантно. Я попытался реализовать его для моделей форм. У меня сложилось впечатление, что я не могу вызывать статические методы внутри класса, но необъяснимо работает следующее:
На мой взгляд, если я сделаю что-то вроде этого:
Затем ключевое слово «request» распространяется на все формы-члены моего набора форм. Я доволен, но я понятия не имею, почему это работает - кажется, неправильно. Какие-либо предложения?
источник
MyFormSet.form.Meta.model
.MyFormSet.form().Meta.model
, На самом деле очевидно.Я потратил некоторое время, пытаясь выяснить эту проблему, прежде чем увидел эту публикацию.
Решением, которое я придумал, было решение замыкания (и это решение, которое я использовал раньше с модельными формами Django).
Я попробовал метод curry (), как описано выше, но я просто не мог заставить его работать с Django 1.0, поэтому в итоге я вернулся к методу закрытия.
Метод замыкания очень аккуратен, и единственная небольшая странность заключается в том, что определение класса вложено в представление или другую функцию. Я думаю, тот факт, что это выглядит странно для меня, является следствием моего предыдущего опыта программирования, и я думаю, что кто-то с опытом работы в более динамичных языках не будет биться век!
источник
Я должен был сделать подобное. Это похоже на
curry
решение:источник
На основании этого ответа я нашел более четкое решение:
И запустить его в виду, как
источник
Я новичок здесь, поэтому я не могу добавить комментарий. Я надеюсь, что этот код тоже будет работать:
что касается добавления дополнительных параметров в форму набора
BaseFormSet
вместо формы.источник