Flask/WTForms/QuerySelectField-使用基于现有数据库值选择的选项来呈现QuerySelectField [英] Flask/WTForms/QuerySelectField - render QuerySelectField with a choice selected based on existing database value

查看:61
本文介绍了Flask/WTForms/QuerySelectField-使用基于现有数据库值选择的选项来呈现QuerySelectField的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在构建一个包含配置文件管理页面的简单CMS.在此配置文件页面以及其他字段上,存在一个下拉列表,我使用wtforms扩展的QuerySelectField从表"parks"生成该列表:

I am building a simple CMS that includes a profile management page. On this profile page, along with other fields, there exists a dropdown list, which I generate from a table 'parks' using the wtforms extension's QuerySelectField:

from wtforms.ext.sqlalchemy.fields import QuerySelectField

个人资料页面上的其余字段由用户"表填充.

The rest of the fields on the profile page are populated by the 'user' table.

让我们假设一个用户已经登录,并且在用户"表中的记录已经被填充.用户"表中的字段中有一个外键,用于表示公园"表中的值:"park_id".

Let assume that a user has logged in, and that their record in the 'user' table is already populated. Among the fields in the 'user' table is a foreign key for a value from the 'parks' table: 'park_id'.

当登录的用户导航到其个人资料页面时,我想在下拉列表中显示与该用户的park_id外键值相对应的选择.

When a logged in user navigates to their profile page, I would like to display the selection in the dropdown that corresponds to this user's park_id foreign key value.

请注意,Flask/Python等对我来说是非常新的.另外,我使用的是Flask-Security,下面的User模型基于他们的示例.也许我需要与用户/公园建立另一种关系?

Note that Flask/Python et al is very new to me. Also, I am using Flask-Security and the User model below is based off their examples. Perhaps I need to build another relationship with users/parks?

显示用户保存的配置文件信息,包括可能出现在下拉列表中以便进行编辑的信息,对我来说似乎很基础.我担心我缺少基本的东西.到目前为止,关于SO和其他地方的其他类似问题/答案似乎令我感到困惑.

Displaying a user's saved profile information, including that which might appear in a dropdown list to be made available for editing seems very basic to me. I fear I'm missing something fundamental. So far, other similar questions/answers on SO and elsewhere seem wildly confusing to me.

我的用户模型:

# Define models
roles_users = db.Table('roles_users',
        db.Column('user_id', db.Integer(), db.ForeignKey('user.id')),
        db.Column('role_id', db.Integer(), db.ForeignKey('role.id')))

class Role(db.Model, RoleMixin):
    id = db.Column(db.Integer(), primary_key=True)
    name = db.Column(db.String(80), unique=True)
    description = db.Column(db.String(255))

class User(db.Model, UserMixin):
    id = db.Column(db.Integer, primary_key=True)
    email = db.Column(db.String(255), unique=True)
    password = db.Column(db.String(255))
    active = db.Column(db.Boolean())
    confirmed_at = db.Column(db.DateTime())
    roles = db.relationship('Role', secondary=roles_users,
                            backref=db.backref('users', lazy='dynamic'))
    park_id = db.Column(db.Integer)
    weather_zip = db.Column(db.String(255))
    flickr_api_key = db.Column(db.String(255))
    flickr_api_secret = db.Column(db.String(255))
    flickr_user_id = db.Column(db.String(255))
    flickr_photo_set_id = db.Column(db.String(255))

我的公园模型:

class Parks(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    park = db.Column(db.String(255))

我的个人资料表格(带有query_factory的东西)

My Profile Form (with query_factory thing)

def get_parks():
    return Parks.query

class ProfileForm(Form):
    id = HiddenField()
    email = HiddenField()
    park_id = QuerySelectField('Park',[validators.InputRequired(u'Please select a park')], default=19, query_factory=get_parks, get_label='park', allow_blank=True)
    weather_zip = StringField('Zip Code',[validators.Length(min=5, max=5, message=u'Zip must contain 5 numbers'), validators.InputRequired(u'please enter a 5-digit zip code')])
    flickr_api_key = StringField('Flickr API Key', [validators.InputRequired(u'Please supply a Flickr API key')])
    flickr_api_secret = StringField('Flickr API Secret', [validators.InputRequired(u'Please supply a Flickr API secret')])
    flickr_user_id = StringField('Flickr User ID', [validators.InputRequired(u'Please supply a Flickr user id')])
    flickr_set_id = StringField('Flickr Set ID', [validators.InputRequired(u'Please supply a Flickr set id')])

我的个人资料页面浏览量:

My profile_page view:

@app.route('/profile/<id>', methods=["GET","POST"])
@login_required
def profile_page(id):

    id = id
    current_user = User.query.filter_by(id=id).first()

    form = ProfileForm(obj=current_user)

    return render_template("profile.html", form=form)

我的模板的形式:

    {% from "_formhelpers.html" import render_field %}
    <form method=post action="/profile">
      <dl>
        {{ form.id(value=current_user.id) }}
        {{ form.email(value=current_user.email) }}
        {{ render_field(form.park_id) }}
        {{ render_field(form.weather_zip) }}
        {{ render_field(form.flickr_api_key) }}
        {{ render_field(form.flickr_api_secret) }}
        {{ render_field(form.flickr_user_id) }}
        {{ render_field(form.flickr_set_id) }}
      </dl>
      <p><input type=submit value=Register>
    </form>

用于渲染字段的宏(可能相关吗?):

A macro to render the fields (might be relevant?):

{% macro render_field(field) %}
    <dt>{{ field.label }}
    <dd>{{ field(**kwargs) |safe }}
    {% if field.errors %}
        <ul class=errors>
        {% for error in field.errors %}
            <li>{{ error }}</li>
        {% endfor %}
        </ul>
    {% endif %}
    </dd>
{% endmacro %}

感谢所有这些帮助.

推荐答案

喝了几杯啤酒并出演了这篇文章之后:

After drinking a couple beers and starring at this post: SQLAlchemy/WTForms: set default selected value for QuerySelectField until my eyes crossed, I discovered that I needed to pass a result object from a query to my parks table filtered by the current user's id.

一个特殊的细节是,我不得不从当前用户的查询结果中手动分配每个字段值(除了QuerySelectField,parks).这是因为,就我而言,仅将current_user结果传递给"obj =" arg将会覆盖我的QuerySelectField关键字(在我的情况下为"park_id"),因为"obj = current_user"分配已经包含了其自己的park_id参数实例,尽管该选项无法在我的下拉菜单中显示默认选择.

A special detail is that I had to manually assign each field value (aside from the QuerySelectField, parks) from the current user's query result. This is because, in my case, simply passing the current_user result to the "obj=" arg would override my QuerySelectField keyword (in my case "park_id") because the "obj=current_user" assignment already contains its own instance of the park_id parameter, albeit one that doesn't work for displaying a default selection in my drop down.

所以...解决方法是按如下方式更新我的profile_page视图功能:

So... The fix was to update my profile_page view function as follows:

@app.route('/profile/<id>', methods=["GET","POST"])
@login_required
def profile_page(id):

    id = id
    current_user = User.query.filter_by(id=id).first()
    park = Parks.query.filter_by(id=current_user.park_id).first()
    form = ProfileForm(park_id=park, # this is the main thing
                       weather_zip=current_user.weather_zip,
                       flickr_api_key=current_user.flickr_api_key,
                       flickr_api_secret=current_user.flickr_api_secret,
                       flickr_user_id=current_user.flickr_user_id,
                       flickr_photo_set_id=current_user.flickr_photo_set_id)

    return render_template("profile.html", form=form)

这篇关于Flask/WTForms/QuerySelectField-使用基于现有数据库值选择的选项来呈现QuerySelectField的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆