简体   繁体   English

Flask WTFORMS 从表中构建 SelectField

[英]Flask WTFORMS building a SelectField from a table

I am pulling my hair out with this as I haven't had any issues with flask or WTForms and have built quite a large application so far.我正在为此拉扯头发,因为我对 flask 或 WTForms 没有任何问题,并且到目前为止已经构建了相当大的应用程序。 Here is what I am trying to do.这是我想要做的。

I have 2 data models, Subscription, and Billing interval.我有 2 个数据模型,订阅和计费间隔。 There is a foreign key between the two and everything works well:两者之间有一个外键,一切正常:

class Subscriptions(db.Model):

    __tablename__ = 'subscriptions'

    id = db.Column(db.Integer, primary_key = True)
    name = db.Column(db.String(64))
    description = db.Column(db.String(255))
    lastcrawled = db.Column(db.Date)
    lastcheckedby = db.Column(db.Integer)
    isActive = db.Column(db.Boolean, default = False)
    datecreated = db.Column(db.Date, default = datetime.date.today())
    pricing = db.Column(db.Numeric(10, 2), nullable=True)
    alias = db.Column(db.String(64))
    isQuote = db.Column(db.Boolean, default = True)

    billinginterval_id = db.Column(db.Integer, db.ForeignKey('billinginterval.id'))
    user_id = db.Column(db.Integer, db.ForeignKey('user.id'))

class BillingInterval(db.Model):
    __tablename__ = 'billinginterval'

    id = db.Column(db.Integer, primary_key = True)
    interval = db.Column(db.String(64))
    subscriptions = db.relationship('Subscriptions', backref='billinginterval')

    def __str__(self):
        return self.interval

I have a form where a user can add another subscription:我有一个表单,用户可以在其中添加另一个订阅:

class AddSubscription(FlaskForm):

    name = StringField("Name", validators=[DataRequired()])
    description = TextAreaField('Description')
    pricing = IntegerField('Pricing')
    billinginterval = SelectField('Billing Interval',choices=BillingInterval.query.all())
    submit = SubmitField("Add Subscription")

And finally here is my Template:最后是我的模板:

{% extends "layout.html" %}
{% block content %}
    <form method="POST">
        {# This hidden_tag is a CSRF security feature. #}
        {{ form.hidden_tag() }}
        {{ form.name.label }} {{ form.name() }}<br>
        {{ form.description.label }} {{ form.description() }}<br>
        {{ form.pricing.label }} {{ form.pricing() }}<br>
        {{ form.billinginterval.label }} {{ form.billinginterval() }}<br>
        {{ form.submit() }}
    </form>
{% endblock %}

I need to have a "SelectField" that populates from the "billinginterval" table (displays interval as the choices) and then writes the billinginterval.id field to the subscription model.我需要一个从“billinginterval”表中填充的“SelectField”(显示间隔作为选项),然后将 billinginterval.id 字段写入订阅 model。

Everything works flawlessly until I try adding this billing interval dropdown.在我尝试添加此计费间隔下拉列表之前,一切都完美无缺。 Just can't get it.就是拿不到。

I've tried everything, I cannot get it to work.我已经尝试了一切,我无法让它工作。 Any help would be grateful.任何帮助将不胜感激。 Thanks!谢谢!

Ok.... I figured this out.好的....我想通了。 Not sure it is the best way.不确定这是最好的方法。

In my Forms.py file I modified the select field:在我的 Forms.py 文件中,我修改了 select 字段:

class AddSubscription(FlaskForm):

    name = StringField("Name", validators=[DataRequired()])
    description = TextAreaField('Description')
    pricing = IntegerField('Pricing')
    #Right HERE!!!!
    billinginterval = SelectField('Billing Interval',choices=[], coerce=int, validate_choice=True)
    #billinginterval = SelectField('Billing Interval',choices=[(1,'Monthly'),(2,'Daily')])
    #billinginterval = QuerySelectField(query_factory=lambda: BillingInterval.query.all())
    #billinginterval = QuerySelectField(query_factory=billinginterval_query, allow_blank=True)
    submit = SubmitField("Add Subscription")

I added ",choices=[], coerce=int, validate_choice=True)" to the billinginterval form field.我在 billinginterval 表单字段中添加了“,choices=[], coerce=int, validate_choice=True)”。

Then in my views.py (routing file) I set the choices variable:然后在我的views.py(路由文件)中设置选择变量:

def addsubscription(userid):
    form = AddSubscription()

    form.billinginterval.choices = [(interval.id, interval.interval) for interval in BillingInterval.query.all()]
    #print(form.billinginterval.data)
    if form.validate_on_submit():

        subscription = Subscriptions(name=form.name.data,
                    description=form.description.data,
                    lastcheckedby=current_user.id,
                    isActive=True,
                    user_id=userid,
                    billinginterval_id=form.billinginterval.data,
                    alias = random.getrandbits(32))    

        db.session.add(subscription)
        db.session.commit()

        subscriptions = Subscriptions.query.all()

        #flash('Thanks for registering! Now you can login!')
        return redirect(url_for('admin.managesubscriptions', userid=userid))
    return render_template('addsubscription.html', form=form)
    ```
And loaded it manually from my data model.

All works now. Hope this solution helps someone!

The best practice is to load the choices in the __init__ method of your AddSubscription class:最佳做法是在AddSubscription class 的__init__方法中加载choices

class AddSubscription(FlaskForm):
    name = StringField("Name", validators=[DataRequired()])
    description = TextAreaField('Description')
    pricing = IntegerField('Pricing')
    billinginterval = SelectField('Billing Interval', coerce=int)
    submit = SubmitField("Add Subscription")

    def __init__(self, *args, **kwargs):
        super(AddSubscription, self).__init__(*args, **kwargs)
        self.billinginterval.choices = [(interval.id, interval.interval) 
                                        for interval in BillingInterval.query.all()]

Then you will not load the choices in every view functions where you will use AddSubscription form.然后,您将不会在将使用AddSubscription表单的每个视图函数中加载choices

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM