如何使用sqlalchemy多对多关系实例化wtforms.ext.sqlalchemy.fields.QuerySelectMultipleField

如何使用sqlalchemy多对多关系实例化wtforms.ext.sqlalchemy.fields.QuerySelectMultipleField,sqlalchemy,flask,flask-sqlalchemy,wtforms,flask-wtforms,Sqlalchemy,Flask,Flask Sqlalchemy,Wtforms,Flask Wtforms,我正在尝试使用wtforms.ext.sqlalchemy QuerySelectMultipleField显示复选框列表,但无法在get上获取要在表单上显示的模型数据 这是我的模特 user_permissions = db.Table('user_permissions', db.Column('permission_id', db.Integer, db.ForeignKey('permission.id')), db.Column('user_id', db.Intege

我正在尝试使用wtforms.ext.sqlalchemy QuerySelectMultipleField显示复选框列表,但无法在get上获取要在表单上显示的模型数据

这是我的模特

user_permissions = db.Table('user_permissions',
    db.Column('permission_id', db.Integer, db.ForeignKey('permission.id')),
    db.Column('user_id', db.Integer, db.ForeignKey('user.id'))
)

class User(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(80), nullable=False, unique=True)
    email = db.Column(db.String(120), nullable=False, unique=True)
    password = db.Column(db.String(80), nullable=False)

    permissions = db.relationship('Permission', secondary=user_permissions, 
            backref=db.backref('permissions', lazy='dynamic'))

    def __init__(self, username, email, password):
        self.username = username
        self.email = email
        self.password = password

    def __repr__(self):
        return '<User %r>' % self.username


class Permission(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    desc = db.Column(db.String(80), nullable=False)

    def __init__(self, desc):
        self.desc = desc

    def __repr__(self):
        return '<Permission %r>' % self.desc
这是我的观点

@app.endpoint('edit_user')
@require_login()
@require_permission('edit_user')
def edit_user(user_id):
    user = User.query.filter_by(id=user_id).first()
    if not user:
        abort(404)
    data = {
        "username": user.username,
        "email": user.email,
        "permissions": user.permissions
    }
    form = EditUserForm(**data)
问题是WTForm没有显示从user.permissions(权限模型列表)中选择的值。它显示一个空复选框列表

(Pdb) print user.permissions
[<Permission u'admin'>, <Permission u'create_user'>, <Permission u'edit_user'>]
有几个问题

1) 查询工厂的操作方式可能会导致问题,因为它可能与单个会话/查询工厂关联。这意味着您要比较的对象与查询工厂中的对象不在同一会话中

更安全的方法是:

    query_factory=lambda: Permission.query.all()
2) 我假设您使用的是Flask WTF,因为您没有传递formdata部分,但是如果您没有传递(您使用的是wtforms.Form),那么请执行以下操作:

form = EditUserForm(request.form)
3) 您将一次性迭代器作为集合传递:

    "permissions": user.permissions
如果您确实需要通过dict自定义传入的数据,您应该这样做:

    "permissions": list(user.permissions)
def edit_user(user_id):
    user = User.query.filter_by(id=user_id).first()
    if not user:
        abort(404)

    form = EditUserForm(request.form, user)
    [...]
然而,由于dict是多么基本,因此更倾向于将数据作为对象传递(这应该避免单次使用迭代器的问题)


将这一切结合在一起,您的视图应该如下所示:

    "permissions": list(user.permissions)
def edit_user(user_id):
    user = User.query.filter_by(id=user_id).first()
    if not user:
        abort(404)

    form = EditUserForm(request.form, user)
    [...]
def edit_user(user_id):
    user = User.query.filter_by(id=user_id).first()
    if not user:
        abort(404)

    form = EditUserForm(request.form, user)
    [...]