动态 WTForms SelectField 在数据库中显示 table 的 column-title

dynamic WTForms SelectField shows the column-title of table in the db

我正在尝试通过 flask sql-alchemy 从 SQL-Table 'School' 中将数据提取到 SelectField 中:

形式:

school_choices = [(School.id, School.name) for school in School.query.all()]
school = SelectField('Your school', validators=[DataRequired()], choices=school_choices)

路线:

def register():
if current_user.is_authenticated:
    return redirect(url_for('home'))
form = RegistrationForm()
if form.validate_on_submit():
    hashed_password = bcrypt.generate_password_hash(form.password.data).decode('utf-8')
    user = User(username=form.username.data, email=form.email.data, password=hashed_password, school=form.school.data)
    db.session.add(user)
    db.session.commit()
    flash('Your account has been created! You are now able to log in', 'success')
    return redirect(url_for('login'))
return render_template('register.html', title='Register', form=form)

型号:

class School(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(100), nullable=False)

然而,它不知何故只显示 "School.name",就像它在表格中的写法一样。 此外,它应该显示的条目数是正确的(3,因为数据库中有 3 个学校条目)

问题出在您的列表理解中,它构建了 select 字段的值以及 class 与 class 实例上列属性呈现之间的差异:

school_choices = [(School.id, School.name) for school in School.query.all()]

在上面的理解中,在每个循环中school(小写's')是class(大写'S')的一个实例。

在 sqlalchemy 中,Class 上列属性的字符串表示(不是 class 的实例)returns 列的数据库标识,例如:"<tablename>.<columnname>",或者在本例中为 "school.name"。这就是构建查询的方式,例如试试 运行 print(School.__table__.select()),它会打印 SELECT school.id, school.name FROM School。该查询中的列标识来自 "stringifying" Column 实例。

但是,当我们访问 class 的实例上的列属性时,例如school = School(name="myschool"),我们获取存储在数据库中的列的值。例如。 print(school.school) # myschool.

查看上面的列表理解,您为数据库中的每个 school 实例创建了一个 (School.id, School.name) 的元组。请注意 'School' 的大写 'S',这意味着当您的模板呈现时,您最终会呈现数据库中每个学校的列的数据库标识的字符串表示形式。答案很简单,只需将您的理解改为:

school_choices = [(school.id, school.name) for school in School.query.all()]

...但是在一般情况下使用 sqlalchemy 和 python 时,了解差异非常重要。