5 Stimmen

Django-Formular-Assistent - Auswahlmöglichkeiten abhängig vom ersten Formularschritt

Ich habe ein 2-stufiges Formular mit dem FormWizard wie folgt erstellt:

  • 1. Schritt: Benutzer nach Standort fragen
  • 2. Schritt: mehrere Suchergebnisse anzeigen abhängig am Standort des Benutzers und zeigen sie als radioButtons an

Die zweite Form hängt nun von der Eingabe der ersten Form ab. Mehrere Blogs oder Stackoverflow-Beiträge behandeln ähnliche Themen, und ich habe die Anweisungen befolgt. Die Variable, die während des process_step gespeichert werden soll, ist jedoch für den nächsten Schritt nicht verfügbar _ init _.

Wie übermittle ich den Ort der Variablen vom Prozessschritt an _ 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/')

Für jede Hilfe sind wir dankbar.

Danke! H

PS: Der Beitrag wurde mit neuerem Code aktualisiert.

10voto

Yuji 'Tomita' Tomita Punkte 110771

Ich dachte, Sie könnten einfach auf die POST Wörterbuch direkt in Ihrem __init__ Methode, weil es so aussieht, als ob der Assistent die POST in jede Formularinstanz über get_form aber ich sehe die Daten aus irgendeinem Grund nicht.

Anstatt sich zu lange damit aufzuhalten, habe ich eine Alternative gefunden, nämlich die Verwendung der render_template Haken.

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)

6voto

Guy Bowden Punkte 4797

Sie können die Daten aus einem beliebigen Schritt abrufen, indem Sie das Speicherobjekt verwenden:

self.storage.get_step_data('0')

werden die im Speicher-Backend gespeicherten Daten für diesen Schritt zurückgegeben.

In meinem Beispiel unten enthält das erste Formular eine Dropdown-Auswahl "Aktivität". Das zweite Formular enthält ein Standortauswahl-Widget, das nur Standorte anzeigt, die für diese Aktivität verfügbar sind.

Dies funktioniert, wenn Sie im Assistenten vorwärts oder rückwärts gehen - die obigen Antworten funktionieren nicht, wenn Sie "prev" drücken, da sie davon ausgehen, dass der Assistent nur vorwärts geht (d. h. das POST-Diktat enthält nicht die Daten von Schritt 0, wenn Sie bei Schritt 3 prev drücken!)

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

1voto

Hannes Punkte 109

Der funktionierende Code, nachdem ich das Problem mit Yuji's Hilfe (Danke) gelöst habe, ist:

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)

9 Stimmen

Ich weise Sie nur darauf hin, dass Sie meine Antwort nicht als Ihre Antwort wiedergeben sollten. Sie sollten die Antwort akzeptieren, die Ihnen weiterhilft, und Ihre Frage mit einer Code-Aktualisierung bearbeiten.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X