Мастер форм Django - выбор в зависимости от первого шага формы - PullRequest
5 голосов
/ 19 февраля 2011

Я создал двухшаговую форму с помощью FormWizard следующим образом:

  • 1-й шаг: запрос пользователя о местоположении
  • 2-й шаг: показать несколько результатов поиска в зависимости на месте пользователя и отображать его как radioButtons

Теперь вторая форма зависит от ввода первой формы.Несколько блогов или сообщений от stackoverflow охватывают похожие темы, и я следовал инструкциям. Однако переменная, которая должна быть сохранена во время шага процесса, недоступна для следующего _ init _.

Как передать переменнуюрасположение от process_step до _ init _?

class reMapStart(forms.Form):
    location = forms.CharField()
    CHOICES = [(x, x) for x in ("cars", "bikes")]
    technology = forms.ChoiceField(choices=CHOICES)

class reMapLocationConfirmation(forms.Form):

   def __init__(self, user, *args, **kwargs):
       super(reMapLocationConfirmation, self).__init__(*args, **kwargs)
       self.fields['locations'] = forms.ChoiceField(widget=RadioSelect(), choices=[(x, x)  for x in location])

class reMapData(forms.Form):
   capacity = forms.IntegerField()

class reMapWizard(FormWizard):
   def process_step(self, request, form, step):
       if step == 1:
          self.extra_context['location'] = form.cleaned_data['location']

   def done(self, request, form_list):
       # Send an email or save to the database, or whatever you want with
       # form parameters in form_list
       return HttpResponseRedirect('/contact/thanks/')

Любая помощь приветствуется.

Спасибо, H

PS: пост был обновлен с более новым кодом.

Ответы [ 3 ]

9 голосов
/ 19 февраля 2011

Я подумал, что вы можете просто получить доступ к словарю POST непосредственно в вашем методе __init__, потому что похоже, что мастер передает POST в каждый экземпляр формы через get_form, но я не вижу данных для некоторыхпричина.

Вместо того, чтобы останавливаться на этом слишком долго, альтернативой, которую я придумал, является использование крюка render_template.

class ContactWizard(FormWizard):
    def done(selef, request, form_list):
        return http.HttpResponse([form.cleaned_data for form in form_list])

    def render_template(self, request, form, previous_fields, step, context=None):
        """
        The class itself is using hidden fields to pass its state, so
        manually grab the location from the hidden fields (step-fieldname)
        """
        if step == 2: 
            locations = Location.objects.filter(location=request.POST.get('1-location'))
            form.fields['locations'].choices = [(x, x) for x in locations]
        return super(ContactWizard, self).render_template(request, form, previous_fields, step, context)
6 голосов
/ 22 июля 2012

Вы можете получить данные с любого шага, используя объект хранилища:

self.storage.get_step_data('0')

. Это вернет данные, сохраненные в серверной части хранилища для этого конкретного шага.

В моемВ приведенном ниже примере первая форма содержит выпадающий список «Активность».Затем вторая форма содержит виджет выбора местоположения, который показывает только местоположения, доступные для этого действия.

Это работает, когда вы переходите вперед или назад через мастер - вышеуказанные ответы не работают, если вы нажимаете 'prev«поскольку они полагаются на то, что мастер будет двигаться только вперед (т. е. диктовка POST не будет содержать данные шага 0, если вы нажмете prev на шаге 3!)

def get_form(self, step=None, data=None, files=None):

    form = super(EnquiryWizard, self).get_form(step, data, files)
    #print self['forms']['0'].cleaned_data

    step = step or self.steps.current

    if step == '1':
        step_0_data = self.storage.get_step_data('0')
        activity = Activity.objects.get(pk=step_0_data.get('0-activity'))
        locations = Location.objects.filter(activities=activity)
        form.fields['locations'].widget = forms.CheckboxSelectMultiple(choices=[(x.pk,x.name) for x in locations])

    return form
1 голос
/ 19 февраля 2011

Рабочий код после решения проблемы с помощью Юджи (спасибо):

class reMapWizard(FormWizard):

    def render_template(self, request, form, previous_fields, step, context=None):
        if step == 1:
            location = request.POST.get('0-location')
            address, lat, lng, country = getLocation(location)
            form.fields['locations'] = forms.ChoiceField(widget=RadioSelect(), choices = [])
            form.fields['locations'].choices = [(x, x) for x in address]
        return super(reMapWizard, self).render_template(request, form, previous_fields, step, context)
...