Django Передача пользовательских параметров формы в Formset

Похоже, никто не говорил об этом варианте использования Pivot в добавлении к MapReduce. Существует хорошая статья, которая может быть вашим ответом здесь http://cookbook.mongodb.org/patterns/pivot/ Надеюсь, это поможет вам в ваших проектах

140
задан Paolo Bergantino 31 March 2016 в 16:24
поделиться

5 ответов

Я использовал бы functools.partial и functools.wraps:

from functools import partial, wraps
from django.forms.formsets import formset_factory

ServiceFormSet = formset_factory(wraps(ServiceForm)(partial(ServiceForm, affiliate=request.affiliate)), extra=3)

я думаю, что это - самый чистый подход и не влияет на ServiceForm всегда (т.е. мешая разделять на подклассы).

104
ответ дан Carl Meyer 31 March 2016 в 16:24
поделиться
  • 1
    Это - оригинал документа, который я отправил джедаю об этом, он обеспечивает объяснение, почему сделать это: stack.nl/~marcov/porting.pdf (глава 2) – Marco van de Voort 9 July 2009 в 13:50

Мне нравится решение для закрытия за то, что оно было "инструментом для очистки" и большим количеством Pythonic (так +1 к ответу mmarshall), но формы Django также имеют механизм обратного вызова, который можно использовать для фильтрации querysets в formsets.

Это также не документируется, который я думаю, индикатор, Django devs не мог бы понравиться он так же.

, Таким образом, Вы в основном создаете свой formset то же, но добавляете обратный вызов:

ServiceFormSet = forms.formsets.formset_factory(
    ServiceForm, extra=3, formfield_callback=Callback('option', affiliate).cb)

Это создает экземпляр класса, который похож на это:

class Callback(object):
    def __init__(self, field_name, aff):
        self._field_name = field_name
        self._aff = aff
    def cb(self, field, **kwargs):
        nf = field.formfield(**kwargs)
        if field.name == self._field_name:  # this is 'options' field
            nf.queryset = ServiceOption.objects.filter(affiliate=self._aff)
        return nf

Это должно дать Вам общее представление. Это - немного более сложное создание обратного вызова метод объекта как это, но дает Вам немного больше гибкости в противоположность выполнению простого функционального обратного вызова.

9
ответ дан Van Gale 31 March 2016 в 16:24
поделиться

Я создал бы класс формы динамично в функции, так, чтобы он имел доступ к филиалу через закрытие:

def make_service_form(affiliate):
    class ServiceForm(forms.Form):
        option = forms.ModelChoiceField(
                queryset=ServiceOption.objects.filter(affiliate=affiliate))
        rate = forms.DecimalField(widget=custom_widgets.SmallField())
        units = forms.IntegerField(min_value=1, 
                widget=custom_widgets.SmallField())
    return ServiceForm

В качестве награды, Вы не должны переписывать queryset в поле опции. Оборотная сторона - то, что разделение на подклассы немного броско. (Любой подкласс должен быть сделан похожим способом.)

редактирование:

В ответ на комментарий, можно вызвать эту функцию о любом месте, Вы использовали бы имя класса:

def view(request):
    affiliate = get_object_or_404(id=request.GET.get('id'))
    formset_cls = formset_factory(make_service_form(affiliate))
    formset = formset_cls(request.POST)
    ...
45
ответ дан Matthew Marshall 31 March 2016 в 16:24
поделиться

I wanted to place this as a comment to Carl Meyers answer, but since that requires points I just placed it here. This took me 2 hours to figure out so I hope it will help someone.

A note about using the inlineformset_factory.

I used that solution my self and it worked perfect, until I tried it with the inlineformset_factory. I was running Django 1.0.2 and got some strange KeyError exception. I upgraded to latest trunk and it worked direct.

I can now use it similar to this:

BookFormSet = inlineformset_factory(Author, Book, form=BookForm)
BookFormSet.form = staticmethod(curry(BookForm, user=request.user))
9
ответ дан 23 November 2019 в 22:49
поделиться

Я потратил некоторое время, пытаясь выяснить эту проблему, прежде чем увидел эту публикацию.

Решение, которое я придумал, было решением для закрытия (и это решение, которое я использовал раньше с модельными формами Django).

Я попробовал метод curry (), как описано выше, но мне просто не удалось заставить его работать с Django 1.0, поэтому в конце концов я вернулся к методу закрытия.

Метод закрытия очень аккуратно, и единственная небольшая странность заключается в том, что определение класса вложено в представление или другую функцию. Я думаю, что тот факт, что мне это кажется странным, является зависанием от моего предыдущего опыта программирования, и я думаю, что кто-то с опытом работы с более динамичными языками не моргнет глазом!

1
ответ дан 23 November 2019 в 22:49
поделиться
Другие вопросы по тегам:

Похожие вопросы: