首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何用wtforms.ext.sqlalchemy.fields.QuerySelectMultipleField多到多关系实例化SQLAlchemy

如何用wtforms.ext.sqlalchemy.fields.QuerySelectMultipleField多到多关系实例化SQLAlchemy
EN

Stack Overflow用户
提问于 2013-09-15 17:34:55
回答 1查看 1.8K关注 0票数 4

我试图使用wtforms.ext.sqlalchemy QuerySelectMultipleField显示一个复选框列表,但无法获得要在GET上的表单上显示的模型数据。

这是我的models.py

代码语言:javascript
复制
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

这是我的forms.py

代码语言:javascript
复制
class EditUserForm(Form):
    username = TextField('Name', validators=[DataRequired()])
    email = TextField('Email', validators=[DataRequired()])
    permissions = QuerySelectMultipleField(
            query_factory=Permission.query.all,
            get_label=lambda a: a.desc,
            widget=widgets.ListWidget(prefix_label=False),
            option_widget=widgets.CheckboxInput()
    )

这是我的views.py

代码语言:javascript
复制
@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的选定值,这是权限模型的列表。它显示一个空复选框列表。

代码语言:javascript
复制
(Pdb) print user.permissions
[<Permission u'admin'>, <Permission u'create_user'>, <Permission u'edit_user'>]

我相当肯定问题在于“权限”数据值是如何构造的,但我已经尝试了所有我能想到的可能性。任何帮助都将不胜感激。

有些事我试过了..。

代码语言:javascript
复制
"permissions": [1, 2]
"permissions": ['1', '2']
"permissions": ['permissions-1', 'permissions-2']
"permissions": [('permissions', 1), ('permissions', 2)]
"permissions": [('permissions', '1'), ('permissions', '2')]
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2013-09-17 19:37:10

几个问题。

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

一个更安全的方法是这样做:

代码语言:javascript
复制
    query_factory=lambda: Permission.query.all()

2)我假设您使用的是Flask,因为您没有传递一个formdata部分,但是如果您没有传递(您使用的是wtforms.Form),那么就这样做:

代码语言:javascript
复制
form = EditUserForm(request.form)

3)您将一个单使用迭代器作为集合传递:

代码语言:javascript
复制
    "permissions": user.permissions

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

代码语言:javascript
复制
    "permissions": list(user.permissions)

然而,由于dict是多么的基本,所以它更倾向于将数据作为一个对象传递(这应该避免单用途迭代器的问题)。

代码语言:javascript
复制
form = EditUserForm(obj=user)

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

代码语言:javascript
复制
def edit_user(user_id):
    user = User.query.filter_by(id=user_id).first()
    if not user:
        abort(404)

    form = EditUserForm(request.form, user)
    [...]
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/18815379

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档