Flask WTFORMS строит SelectField из таблицы - PullRequest
0 голосов
/ 01 августа 2020

Я выдергиваю волосы из-за этого, так как у меня не было никаких проблем с flask или WTForms, и я пока создал довольно большое приложение. Вот что я пытаюсь сделать.

У меня есть 2 модели данных, подписка и интервал выставления счетов. Между ними есть внешний ключ, и все работает хорошо:

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

У меня есть форма, в которой пользователь может добавить еще одну подписку:

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")

И, наконец, вот мой шаблон:

{% 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 %}

Мне нужно иметь «SelectField», который заполняется из таблицы «billinginterval» (отображает интервал в качестве вариантов выбора), а затем записывает поле billinginterval.id в модель подписки.

Все работает безупречно, пока я не попробую добавить раскрывающийся список интервала выставления счетов. Просто не получается.

Все перепробовал, не получается заставить работать. Любая помощь будет признательна. Спасибо!

Ответы [ 2 ]

0 голосов
/ 02 августа 2020

Лучше всего загрузить choices в метод __init__ вашего AddSubscription класса:

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()]

Тогда вы не будете загружать choices во все функции просмотра, в которых вы будет использовать форму AddSubscription.

0 голосов
/ 02 августа 2020

Хорошо .... Я разобрался. Не уверен, что это лучший способ.

В моем файле Forms.py я изменил поле выбора:

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")

Я добавил ", choices = [], coerce = int, validate_choice = True) "в поле формы billinginterval.

Затем в моем views.py (файле маршрутизации) я установил переменную choices:

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!
...