flask wtforms

Django, Flask, Bottle, WSGI, CGI…
Antworten
mr_egbert
User
Beiträge: 14
Registriert: Montag 13. Januar 2020, 13:33

Mittwoch 16. September 2020, 07:21

Guten Morgen,

ich versuche in einem Texteingabefeld Daten anzuzeigen, die dann editiert werden können. In einem Auswahlfeld wird ein Datensatz ausgewählt, die Auswahl wird mit einem Submit (post) abgeschickt und dann sollen die Eingabefelder aktualisiert werden.

Code: Alles auswählen

data = Datatable.query.filter_by(id=form.selection.data).first()
form.string_data.data = data.string_data
form.integer_data.data = data.integer_data
Beim Stringfield funktioniert das prima, beim Integerfield geht es nicht.
Warum ist das so?
Eine Lösung wäre

Code: Alles auswählen

{{ form.integer_data(value=form.data.integer_data) }}
Ist das grundsätzlich der bessere Weg?

Hier der ganze Beispielcode:

Code: Alles auswählen

from flask import Flask, render_template, request
from flask_sqlalchemy import SQLAlchemy
from flask_wtf import FlaskForm
from wtforms import StringField, IntegerField, SelectField, SubmitField

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///site.db'
app.config['SECRET_KEY'] = 'ed20926b80c986c23d4d955401e78118'
db = SQLAlchemy(app)

class Datatable(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    string_data = db.Column(db.String(30), unique=True, nullable=False)
    integer_data = db.Column(db.Integer, nullable=False)

class Testform(FlaskForm):
    selection = SelectField('Auswahl', choices=[])
    submit = SubmitField('submit')
    string_data = StringField('Stringfield')
    integer_data = IntegerField('Integerfield')

@app.route('/', methods=['GET', 'POST'])
def index():
    form = Testform()
    select_list = []
    entries = Datatable.query.all()
    for entry in entries:
        select_list.append([str(entry.id), "   ".join([entry.string_data, str(entry.integer_data)])])
    form.selection.choices = select_list
    if request.method == 'POST':
        for key in request.form.keys():
            print(key, request.form[key])
        data = Datatable.query.filter_by(id=form.selection.data).first()
        form.string_data.data = data.string_data
        form.integer_data.data = data.integer_data
    return render_template('show_test_form.html', form=form)

# def create_db():
#     db.create_all()
#     for entry in [Datatable(string_data='Hans', integer_data=20),
#                   Datatable(string_data='Peter', integer_data=30),
#                   Datatable(string_data='Ulli', integer_data=40)]:
#         db.session.add(entry)
#     db.session.commit()

if __name__ == '__main__':
    app.run(debug=True)

Code: Alles auswählen

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Testform</title>
</head>
<body>
<form method="post" action="">
    {{ form.hidden_tag() }}
    <br>
    {{ form.selection() }}
    {{ form.submit() }}
    <br><br>
    {{ form.string_data.label() }}
    {{ form.string_data() }}
    <br>
    {{ form.integer_data.label() }}
    {{ form.integer_data() }}
</form>
</body>
</html>
Viele Grüße
einfachTobi
User
Beiträge: 211
Registriert: Mittwoch 13. November 2019, 08:38

Mittwoch 16. September 2020, 07:40

Vermutung: Die Datenbank liefert dir einen String zurück und das IntegerField akzeptiert nur Integer, andere Werte werden ignoriert.
mr_egbert
User
Beiträge: 14
Registriert: Montag 13. Januar 2020, 13:33

Mittwoch 16. September 2020, 09:20

Nein, das Integerfeld wird so oder so nicht aktualisiert.
Sowohl

Code: Alles auswählen

data = Datatable.query.filter_by(id=form.selection.data).first()
form.string_data.data = data.string_data
form.integer_data.data = '95'
als auch

Code: Alles auswählen

data = Datatable.query.filter_by(id=form.selection.data).first()
form.string_data.data = data.string_data
form.integer_data.data = 95
bewirken leider nichts. Das Stringfeld wird nach drücken von 'submit' aktualisiert, das Intergerfeld bleibt leer.
garreth
User
Beiträge: 41
Registriert: Donnerstag 23. Oktober 2014, 12:04

Montag 21. September 2020, 09:54

Also ich hoffe, dass dies wirklich nur ein Test ist. Variablen benennt man nicht nach Datentypen und bei dem Versuch den Fehler nachzuvollziehen habe ich am Ende nur noch "data" gesehen. Wobei klar ist, dass in einer Variable Daten gespeichert werden. Gib den Variablen doch aussagekräftigere Namen, dann kann man deinen Code besser nachvollziehen und vor allem, wenn du in ein paar Tagen mal wieder drüber schaust, tust du dir auch einfacher.

Zu deinem Problem:
class wtforms.fields.IntegerField(default field arguments) - A text field, except all input is coerced to an integer. Erroneous input is ignored and will not be accepted as a value.
Ich denke mal, dass der validator verhindert, dass du da einfach Sachen reinschreiben kannst. Wieso genau kann ich dir nicht sagen, wenn du jetzt aber ein TextField aus deinem IntegerField machst, dann funktioniert dein Code.

Im Prinzip würde ich dir aber auch abraten, dein Programm so aufzubauen.
Statt:

Code: Alles auswählen

if request.method == 'POST':

Solltest du:

Code: Alles auswählen

if form.validate_on_submit():
aufrufen. Auf die Methode "POST" wird immer mit einem redirect() geantwortet.

Vielleicht würde dir auch bei deinem Verständnis von Flask helfen folgendes Tutorial durchzuarbeiten:
https://blog.miguelgrinberg.com/post/th ... ello-world
mr_egbert
User
Beiträge: 14
Registriert: Montag 13. Januar 2020, 13:33

Montag 21. September 2020, 19:27

Vielen Dank für die Antworten.
Das Tutorial steht auf meiner Todo-Liste :) .
Antworten