Seite 1 von 1

BooleanField anhand von gegebenen Daten (nicht )abhaken

Verfasst: Donnerstag 11. August 2022, 08:50
von PythonCodingFun
Hallo Flask-Coder :-)


ich möchte gerne ein mit Hilfe von Jinja2/WTForms (in Flask) Textfelder anhand gespeicherter Daten füllen, was mir an sich gelingt. siehe:

Code: Alles auswählen

 
 <div class="form-group row">
 <div class="col-xs-10">
{{ wtf.form_field(form.name, class='form-control',value=person['name']) }}
 </div>  
Aber wie schaffe ich es das ich Booleanfelder richtig "füllen" kann ?

Denn meine Vorgehensweise ist wohl falsch:

Code: Alles auswählen

<div class="form-check row">
<div class="col-xs-10">
{{ wtf.form_field(form.interested class='form-check',value=person['interested']) }}
</div>
Formklasse:

Code: Alles auswählen

class PersonForm(FlaskForm):
    name = StringField('Name: ', validators=[InputRequired(),
                                               Length(min=2, max=510)])
    #...............................
   interested  = BooleanField('Interessiert: ')
route:

Code: Alles auswählen

@person.route('/persons', methods=['GET'])
def get_skills():
    all_persons = get_all_persons()
    person_form = PersonForm()
    return render_template('persons.html', form=person_form, person_List=all_persons)
model:

Code: Alles auswählen

class Persons(db.Model):
    __tablename__ = "persons"
    id = db.Column(db.Integer, primary_key=True, unique=True, nullable=False)
    name = db.Column(nullable=False)
    #...............................
    interested = db.Column(db.Boolean, nullable=False)

Hinweise: Die get_all_persons() gibt mir alles richtig aus und interested ist ein einfaches boolean. Ich möchte erreichen das wenn interested True ist das dass BooleanField "abgehakt" wird.

Diese Kleinigkeit macht mich noch verrückt, wäre froh wenn mir jemand schreiben könnte was ich falsch mache. :D

Danke :)

Re: BooleanField anhand von gegebenen Daten (nicht )abhaken

Verfasst: Donnerstag 11. August 2022, 09:45
von __blackjack__
@PythonCodingFun: Das sieht komisch aus wie Du das Feld erzeugst. Normalerweise füllt man das `Form`-Objekt mit Werten bevor man das dem Template übergibt. Und im Template steht dann für die beiden Beispiele:

Code: Alles auswählen

{{ form.name(class_="form-control") }}
{{ form.interested(class_="form-check") }}
Wie der Wert aus dem `Form` in das HTML-Element kommt, ist nicht Deine Aufgabe, sondern die des `Widget` das zu dem `Field` im `Form` gehört.

Re: BooleanField anhand von gegebenen Daten (nicht )abhaken

Verfasst: Donnerstag 11. August 2022, 09:53
von PythonCodingFun
__blackjack__ hat geschrieben: Donnerstag 11. August 2022, 09:45 @PythonCodingFun: Das sieht komisch aus wie Du das Feld erzeugst. Normalerweise füllt man das `Form`-Objekt mit Werten bevor man das dem Template übergibt. Und im Template steht dann für die beiden Beispiele:
Ich möchte aber die Felder (in einem Modal) bearbeitbar machen, was mir bei name usw. gelingt aber nicht bei dem Booleanfield

Re: BooleanField anhand von gegebenen Daten (nicht )abhaken

Verfasst: Donnerstag 11. August 2022, 10:26
von __blackjack__
@PythonCodingFun: Das ändert nichts an meiner Antwort. Mach es wie es vorgesehen ist, und WTForms macht die Arbeit, die Du hier manuell versuchst nachzubasteln.

Re: BooleanField anhand von gegebenen Daten (nicht )abhaken

Verfasst: Donnerstag 11. August 2022, 10:29
von PythonCodingFun
__blackjack__ hat geschrieben: Donnerstag 11. August 2022, 10:26 @PythonCodingFun: Das ändert nichts an meiner Antwort. Mach es wie es vorgesehen ist, und WTForms macht die Arbeit, die Du hier manuell versuchst nachzubasteln.
Gut, okay, ich habe es so gemacht

Code: Alles auswählen

{{ form.interested(class_="form-check") }}

Aber das Problem bleibt :shock:

Re: BooleanField anhand von gegebenen Daten (nicht )abhaken

Verfasst: Donnerstag 11. August 2022, 11:34
von __blackjack__
@PythonCodingFun: Welches Problem? Das ist ja nicht alles was Du gemacht hast, Du hast ja auch Code geschrieben der das `Form`-Objekt mit den Daten füllt bevor das an das Template geht. Falls nicht, fehlt das halt noch.

Re: BooleanField anhand von gegebenen Daten (nicht )abhaken

Verfasst: Donnerstag 11. August 2022, 11:49
von PythonCodingFun
__blackjack__ hat geschrieben: Donnerstag 11. August 2022, 11:34 @PythonCodingFun: Welches Problem? Das ist ja nicht alles was Du gemacht hast, Du hast ja auch Code geschrieben der das `Form`-Objekt mit den Daten füllt bevor das an das Template geht. Falls nicht, fehlt das halt noch.
Vielleicht hab ich mich ein wenig falsch ausgedrückt :)

Ich möchte ein Modal öffnen was es mir ermöglicht
1. Die Informationen zu sehen (Name usw.)
2. Diese Information zu ändern

was bei allen Feldern soweit auch klappt, nur eben nicht bei dem Boolean-Feld. Beim Debuggen des Python-Codes sehe ich das die liste richtig befüllt wurde der Wert interested ein True oder False hat.

Re: BooleanField anhand von gegebenen Daten (nicht )abhaken

Verfasst: Donnerstag 11. August 2022, 12:13
von __blackjack__
@PythonCodingFun: Wenn es einen modalen Dialog für mehrere Personen gibt, dann kannst Du das doch sowieso nicht im Template schon mit Daten füllen. Es sei denn Du machst da für jede Person einen eigenen Dialog, was irgendwie ziemlich krass wäre, IMHO.

In dem Fall muss das füllen des `Form`-Objektes mit der jeweiligen Person im Template passieren.

Re: BooleanField anhand von gegebenen Daten (nicht )abhaken

Verfasst: Donnerstag 11. August 2022, 12:22
von PythonCodingFun
__blackjack__ hat geschrieben: Donnerstag 11. August 2022, 12:13 @PythonCodingFun: Wenn es einen modalen Dialog für mehrere Personen gibt, dann kannst Du das doch sowieso nicht im Template schon mit Daten füllen. Es sei denn Du machst da für jede Person einen eigenen Dialog, was irgendwie ziemlich krass wäre, IMHO.
Nein, ich iteriere durch die Personen-Liste durch und alle Werte kommen in eine Tabelle. Und dann kann ich für jede Person ein Modal "anbieten".

Re: BooleanField anhand von gegebenen Daten (nicht )abhaken

Verfasst: Donnerstag 11. August 2022, 12:48
von __blackjack__
@PythonCodingFun: Na dann kannst Du das doch sowieso noch nicht im Template füllen, weil je nach dem welche Person angeklickt wurde um den Dialog anzubieten, müssen da doch andere Daten rein. Da der Server nicht weiss welche Person angeklickt wird, muss das im Browser passieren. Mittels JavaScript.

Re: BooleanField anhand von gegebenen Daten (nicht )abhaken

Verfasst: Donnerstag 11. August 2022, 12:53
von PythonCodingFun
__blackjack__ hat geschrieben: Donnerstag 11. August 2022, 12:48 @PythonCodingFun: Na dann kannst Du das doch sowieso noch nicht im Template füllen, weil je nach dem welche Person angeklickt wurde um den Dialog anzubieten, müssen da doch andere Daten rein. Da der Server nicht weiss welche Person angeklickt wird, muss das im Browser passieren. Mittels JavaScript.
so wie ich es in der Frage geschildert habe, funktioniert es so mit Textfeldern (nur halt nicht mit Booleanfeldern^^)

z.B
Ausschnitt aus dem Modal:

Code: Alles auswählen

<div class="form-group row">
 <div class="col-xs-10">
{{ wtf.form_field(form.name, class='form-control',value=person['name']) }}
 </div>  
Und ich nutze kein JS sondern Flask-Bootstrap und Jinja

Re: BooleanField anhand von gegebenen Daten (nicht )abhaken

Verfasst: Donnerstag 11. August 2022, 13:05
von __blackjack__
@PythonCodingFun: Das kann so nicht funktionieren es sei denn Du erzeugst das eben *doch* für jede Person. Denn woher sollte *ein* modaler Dialog denn sonst wissen welche Person er darstellen soll? Das geht nicht statisch bzw. dynamisch auf dem Server. Da wären wir dann wieder bei „krass“. IMHO.

Letztlich bleibt die Antwort aber immer noch die gleiche. Füll das `Form`-Objekt mit Daten und lass das rendern das zum `Field` gehörende `Widget` erledigen, anstatt das selbst machen zu wollen. Den Code dafür gibt es ja schon, den muss man nicht noch mal selbst nachbauen.

Re: BooleanField anhand von gegebenen Daten (nicht )abhaken

Verfasst: Donnerstag 11. August 2022, 13:14
von PythonCodingFun
__blackjack__ hat geschrieben: Donnerstag 11. August 2022, 13:05 @PythonCodingFun: Das kann so nicht funktionieren es sei denn Du erzeugst das eben *doch* für jede Person. Denn woher sollte *ein* modaler Dialog denn sonst wissen welche Person er darstellen soll? Das geht nicht statisch bzw. dynamisch auf dem Server. Da wären wir dann wieder bei „krass“. IMHO.
Ich schrieb doch das ich durch die Personenliste durch-iteriere alles in eine Tabelle (html+Bootstrap) schreibe und das was ich (exemplarisch) gezeigt hab für alle Personen aus der DB.

Ich hole mal weiter aus :)
Jede Zeile (also jede Person) hat einen Button "Bearbeiten" (o.ä benannt) bei dem ein Modal geöffnet wird und mir alle Werte dieser Person gezeigt werden und ich diese ändern kann (wie gesagt klappt auch so bei String/Textfeldern etc.)

Re: BooleanField anhand von gegebenen Daten (nicht )abhaken

Verfasst: Donnerstag 11. August 2022, 13:29
von einfachTobi
Die Daten für die einzelnen Modals müssen dann ja schon fest übergeben werden, oder? Sprich du hast nachdem das Template gerendert wurde ein Modal für jede Person im Quelltext stehen. Das macht im in der Regel nicht so, sondern lädt diese Daten dynamisch, wenn das Modal geöffnet wird oder holt eben das Modal nachträglich vom Server, wobei das vermutlich eher umständlich ist.
Mit "Form vorher befüllen" ist gemeint, dass das Form bereits mit den nötigen Inhalten erzeugt wird, bevor es dem Template übergeben wird:

Code: Alles auswählen

@person.route('/persons', methods=['GET'])
def get_skills():
    all_persons = get_all_persons()
    person_form = PersonForm(name="Hans", interested=True)
    return render_template('persons.html', form=person_form, person_List=all_persons)
Daher führt das in Kombination mit meinem ersten Absatz zu einer gewissen Verwunderung.
Der Code oben würde so auch nicht so richtig Sinn ergeben, weil du ja mehrere Forms erzeugen willst:

Code: Alles auswählen

@person.route('/persons', methods=['GET'])
def get_skills():
    all_persons = get_all_persons()
    forms = [PersonForm(name=person.name, interested=person.interested) for person in all_persons]
    return render_template('persons.html', forms=forms, person_List=all_persons)
Dann kannst du im Template über alle Forms iterieren und diese erstellen lassen:

Code: Alles auswählen

{% for form in forms %}
  {{ form.name(class_="form-control") }}
  {{ form.interested(class_="form-check") }}
{% endfor %}
Und genau das ist ungewöhnlich, wenn es um optional angezeigte Daten geht. Hier würde man die Daten (das Form) erst dann abrufen, wenn auch der Modal angezeigt werden soll, also geklickt wurde, statt für alle Personen bereits ein Modal vorzuhalten.

Re: BooleanField anhand von gegebenen Daten (nicht )abhaken

Verfasst: Donnerstag 11. August 2022, 13:37
von PythonCodingFun
@einfachTobi ja das was Du da aufzeigst ist natürlich besser aber ich hab für den unüblichen Weg entschieden es ist eigentlich nur kleiner Prototyp, habe gerade ein schönes Beispiel gefunden mit dem man es noch besser machen kann
Link: https://blog.miguelgrinberg.com/post/be ... -templates

Aber ich werde nur mit dem Booleanfield wahnsinnig (denn Textfields funktionieren ja^^, was mich dann auch verwundert), wenn das klappt baue ich die Anwendung mal um ;)

Re: BooleanField anhand von gegebenen Daten (nicht )abhaken

Verfasst: Donnerstag 11. August 2022, 13:56
von einfachTobi
Ich sehe nicht wie dein Link dein Problem lösen sollte. Es geht doch darum, dass du zwar WTForms verwendest, aber dann im Template dagegen arbeitest.
Hier ein vollständiges Minimalbeispiel:

Code: Alles auswählen

from flask import Flask, render_template
from wtforms import Form, StringField, BooleanField

app = Flask(__name__)


class Person:
    def __init__(self, name, interested):
        self.name = name
        self.interested = interested


class PersonForm(Form):
    name = StringField(label="Name")
    interested = BooleanField(label="Interessiert", default=True)


@app.route("/")
def foo():
    persons = [Person("Hans-Werner", True), Person("Gitte", False), Person("Uta", True)]
    forms = [PersonForm(name=person.name, interested=person.interested) for person in persons]
    return render_template("index.html", forms=forms)


if __name__ == '__main__':
    app.run()
index.html

Code: Alles auswählen

<!DOCTYPE html>
<html lang="en">
<body>
{% for form in forms %}
<form method="GET" action="/">
  <div>
      {{ form.name.label }}:
      {{ form.name }}
      {{ form.interested.label }}:
      {{ form.interested }}
  </div>
</form>
{% endfor %}
</body>
</html>

Re: BooleanField anhand von gegebenen Daten (nicht )abhaken

Verfasst: Donnerstag 11. August 2022, 14:14
von PythonCodingFun
Danke an alle jetzt hab ich wieder was dazugelernt :)

Re: BooleanField anhand von gegebenen Daten (nicht )abhaken

Verfasst: Donnerstag 11. August 2022, 16:03
von PythonCodingFun
einfachTobi hat geschrieben: Donnerstag 11. August 2022, 13:29 Die Daten für die einzelnen Modals müssen dann ja schon fest übergeben werden, oder? Sprich du hast nachdem das Template gerendert wurde ein Modal für jede Person im Quelltext stehen. Das macht im in der Regel nicht so, sondern lädt diese Daten dynamisch, wenn das Modal geöffnet wird oder holt eben das Modal nachträglich vom Server, wobei das vermutlich eher umständlich ist.
Wenn man eine Person-Edit Seite ohne Modal realisiert, sprich in einer eigenen HTML/Jinja Seite, benötigt man doch sicherlich auch so was wie eine Session ? Damit das Back-End "weiß" um welche Entität es sich schlussendlich handelt, oder ? Wären Sessions da eine richtig Wahl oder gäbe es da bessere Ansätze ?

Re: BooleanField anhand von gegebenen Daten (nicht )abhaken

Verfasst: Freitag 12. August 2022, 09:15
von einfachTobi
Ich würde das Datum, das die Person eindeutig identifiziert (in der Regel eine ID) einfach mit dem Formular/dem Link mitschicken. In der Session speichert man eher Daten, die zum Benutzer der Seite gehören.
Also sowas wie:

Code: Alles auswählen

# HTML
<a class="btn" href="{{ url_for('edit_person', person_id=person.id) }}" role="button">

# Python 
@app.route("/person/bearbeiten/<person_id>")
def edit_person(person_id):
    person = get_person(person_id)
    return render_template("edit.html", person=PersonForm(name=person.name, interested=person.interested))