Flask Form in Form - Teil der Registrierung updaten

Django, Flask, Bottle, WSGI, CGI…
Antworten
Zoja
User
Beiträge: 145
Registriert: Freitag 28. Februar 2014, 14:04

ich habe eine Anwendung, wo sich User registrieren können. Das ganze Ding ist eine große Form, mit Email Passwort etc.

Zusätzlich registriert der User eine Company (alles in der selben Form), diese hat Kategorien und zwar max. 10.

Kategorien sind in der DB gespeichert und die Anzahl ist fix und wird nur von mir kontrolliert. Sagen wir wir haben 500 Kategorien insgesammt.

PROBLEM:

Während der User sich nun registriert muss er bis zu 10 Kategorien auswählen für seine Company und ich will nicht alle 500 Kategorien anzeigen. Ich will dass der User in ein Inputfeld sein Produkt eingibt und es wird dann mit %like% eine query erstellt, wo ich die Ergebnisse auf die relevantesten 20 reduziere:

Code: Alles auswählen

searched_categories = session.query(Category).filter(Category.category_name.like('%'+form_category.category_search.data.strip()+'%')).limit(20)
Hierfür habe ich nun eine zweite Form erstellt, die in meiner ersten drin liegt. Ein Problem ist schonmal, dass der erste submit button, der kommt nur die zweite form submitted, das kriege ich aber noch gelöst.

Trotzdem würde die Seite ja neuladen. Ich müsste die bereits eingegebenen Daten aus der Registrierung in einem Cookie speichern und auf eine neue route weiterleiten. D.h. Initiale Route /register und nachdem der User nach eine Kategorie gesucht hat /register/<user-input>. Auf der neuen Route würde ich dann eine neue HTML Datei haben, die 1 zu 1 wie die register aussieht, nur dass die Kategorien limitiert sind, außerdem würde ich bereits ausgefüllte Daten aus dem Cookie laden. Hört sich aber irgendwie nicht richtig an, oder?

---

Eine weite Idee wäre das ganze mit jQuery zu machen und mit display none rumzuspielen. Leute mit noscript würden dann vielleicht Probleme haben, aber es würde so aussehen als ob die Seite nicht neu lädt (was sie ja auch nicht tut). Außerdem spare ich mir cookie und neue route. Ich tendieren zu dieser Lösung.

Wie geht man hier richtig vor? Gibt es vielleicht Methoden bei Flask, die Teile der Seite neuladen und nicht die ganze Seite beim submit?

Hier nochaml etwas code (reduziert auf die wesentliche Struktur):
forms:

Code: Alles auswählen

class RegisterUserForm(Form):
    # infos for user
    email = EmailField('Email', validators=[DataRequired(message="Geben Sie eine Email ein"), Email()])
    password = PasswordField('Passwort', validators=[DataRequired(message="Geben Sie ein Passwort ein"), EqualTo('confirm_password', message=u'Passwörter stimmen nicht überein'), Length(min=5, message="Passwort muss mindestens 5 Zeichen lang sein")])
    confirm_password = PasswordField('Passwort wiederholen')
    # infos for company
    company_name = TextField('Firmenname', validators=[DataRequired(message=u"Wie heißt Ihre Firma?")])
    # infos for category
    category_is_merchant = BooleanField(u"Händler")
    category_is_distributor = BooleanField(u"Großhändler")
    category_is_service = BooleanField("Diensleister")
    category_is_manufacturor = BooleanField("Hersteller")
    # etc...

class SearchCategoryForm(Form):
    category_search = TextField('Nach Branche suchen')
jinja/html:

Code: Alles auswählen

<form class="col-xs-12" id="register-form" enctype="multipart/form-data" method="POST" action="{{ url_for('register', next=request.args.get('next')) }}">


    {{ form.hidden_tag() }}  
      <div id="content-company-data">
        <h2> Firmendaten </h2>
        <div class="content">

     <!-- some data -->

    <form class="col-xs-12" id="search-category-form" enctype="multipart/form-data" method="POST" action="{{ url_for('register', next=request.args.get('next')) }}">
    {{ form_category.hidden_tag() }}

    <div class="form-group">
    {{ form_category.category_search.label }}
    {{ form_category.category_search(class = "form-control", placeholder ="Branche") }}

    {% if form_category.category_search.data.errors %}
        {% for error in form_category.category_search.data.errors %} 
        <p class="flashes-error-form"> {{ error }}</p>
        {% endfor %}
    {% endif %}
    </div>

    <button type="submit" class="btn"> Branche suchen </button>

    </form>

    <!-- some data -->

        <button type="submit" class="btn register-button"> Jetzt Kostenlos Registrieren </button>

</form>
main.py:

Code: Alles auswählen

# register site
@app.route('/registrieren', methods=["GET","POST"])
def register(): 
    if current_user.is_authenticated():
        return redirect(url_for('logged_in'))
    else:
        form = RegisterUserForm()
        form_category = SearchCategoryForm()

        searched_categories = Category.query.order_by(asc("id")).limit(4)

        if form_category.validate_on_submit():
            print "cat form validates"                
            searched_categories = Category.query.order_by(asc("id")).limit(2)

            return redirect(url_for('register'))

        if form.validate_on_submit():
            print "user form validates"

            #adding data to DB here
            return redirect(url_for('unconfirmed'))

        return render_template('register.html', form = form, form_category=form_category, searched_categories=searched_categories)
Benutzeravatar
noisefloor
User
Beiträge: 3853
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,
Ich tendieren zu dieser Lösung.
Via JavaScript ist IMHO die deutlich gängigeren und bessere Lösung.
Gibt es vielleicht Methoden bei Flask, die Teile der Seite neuladen und nicht die ganze Seite beim submit?
Grundsätzlich ist HTTP ja "stateless", heißt: wenn der Server die Seite komplett ausgeliefert hast, ist es fertig. Er bekommt nicht mit, was im Browser läuft - egal, ob du Flask, Django, PHP, ... nutzt. Will / muss die Webseite Daten nachladen, dann eben per JavaScript.

Plan C - so kenne ich es von Webseite, z.B. für Messeanmeldungen - ist, dass du die Hauptkategorieren zeigt und dann über dynamische Menüs ausklappbar - ggf. auch über mehrere Ebenen - gestaltest, bis man zu den Auswahlboxen kommt. Dann sparst du dir das dynamische Nachladen.

Gruß, noisefloor
Zoja
User
Beiträge: 145
Registriert: Freitag 28. Februar 2014, 14:04

noisefloor hat geschrieben:Hallo,
Ich tendieren zu dieser Lösung.
Via JavaScript ist IMHO die deutlich gängigeren und bessere Lösung.
Gibt es vielleicht Methoden bei Flask, die Teile der Seite neuladen und nicht die ganze Seite beim submit?
Grundsätzlich ist HTTP ja "stateless", heißt: wenn der Server die Seite komplett ausgeliefert hast, ist es fertig. Er bekommt nicht mit, was im Browser läuft - egal, ob du Flask, Django, PHP, ... nutzt. Will / muss die Webseite Daten nachladen, dann eben per JavaScript.

Plan C - so kenne ich es von Webseite, z.B. für Messeanmeldungen - ist, dass du die Hauptkategorieren zeigt und dann über dynamische Menüs ausklappbar - ggf. auch über mehrere Ebenen - gestaltest, bis man zu den Auswahlboxen kommt. Dann sparst du dir das dynamische Nachladen.

Gruß, noisefloor
Danke für die Antwort, ungefair so mache ich es gerade.

Hatte aber auch noch was über AJAX und Flask gelesen, sah auch nett aus. Bin aber schon mit der JS Variante so gut wie fertig.

Hier ist das AJAX Beispiel aus dem Netz. Kann man auch direkt online ausführen:
http://code.runnable.com/UiPhLHanceFYAA ... for-python
Antworten