Формы WT:установка значения по умолчанию из поля SQLAlchemy с отношением

StackOverflow https://stackoverflow.com//questions/23051179

Вопрос

Здесь, на SO, есть много вопросов с названиями, которые звучат похоже на то, что я собираюсь описать, но, насколько я могу судить по буквально многочасовым исследованиям, этот вопрос уникален.Итак, поехали!

Я пишу свое первое приложение Flask.Я использую SQLAlchemy для уровня модели и WTForms для обработки форм.Приложение будет легким персональным финансовым менеджером, который я, вероятно, не буду использовать в серьезном бизнесе.У меня есть одна таблица для списка всех транзакций, а другая для всех категорий расходов (продукты, одежда и т.д.).В таблице транзакций есть столбец ("категория"), который ссылается на таблицу категорий.В представлении я представляю список категорий с элементом.

Моя проблема заключается в том, что при редактировании транзакции я не могу понять, как сообщить WTForms установить элементу определенное предопределенное значение.(Да, я знаю, что вы можете установить значение по умолчанию во время определения формы, это не то, о чем я спрашиваю.)

Модель выглядит следующим образом (с удаленными нерелевантными полями):

class Category(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(80), nullable=False, unique=True)
    # ...

class Trans(db.Model):
    # ...
    category_id = db.Column(db.Integer, db.ForeignKey('category.id'))
    category = db.relationship('Category',
                                backref=db.backref('trans', lazy='dynamic'))
    # ...

forms.py:

def category_choices():
    return [('0', '')] + [(c.id, c.name) for c in Category.query.all()]

class TransactionForm(Form):
    # ...
    category = SelectField('Category', coerce=int, validators=[InputRequired()])
    # ...

Маршрут (СООБЩЕНИЕ еще не реализовано):

@app.route('/transactions/edit/<trans_id>', methods=['GET', 'POST'])
def trans_edit(trans_id):
    transaction = Trans.query.get(trans_id)
    form = forms.TransactionForm(obj=transaction)
    form.category.choices = forms.category_choices()
    form.category.default = str(transaction.category.id)
    #raise Exception # for debugging
    return render_template('trans.html',
                           title='Edit Transaction',
                           form=form)

И, наконец, шаблон (Jinja2):

{{ form.category(class='trans-category input-medium') }}

Как вы можете видеть в маршруте, я установил form.category.default из transaction.category.id, но это не работает.Я думаю, моя проблема в том, что я устанавливаю "по умолчанию" после создания формы.Что я скорее вынужден делать, потому что модель берется из базы данных через SQLAlchemy.Основная причина, по-видимому, заключается в том, что form.category - это объект (из-за отношения), с которым WTForms, похоже, не может легко справиться.Не мог же я быть первым, кто столкнулся с этим...Нужно ли мне переработать модель, чтобы она была более совместима с WTForms?Какие у меня есть варианты?

Спасибо!

Это было полезно?

Решение

Я упоминал об этом в своем комментарии.Похоже, вам может быть полезно использовать расширение SQLAlchemy от WTForm.Это создаст выпадающий список категорий в вашей форме перевода.

Вариант использования в моем примере немного отличается.Я связываю запись в блоге с темой.То есть многие посты разделяют одну тему.Я полагаю, что в вашем случае многие транзакции относятся к одной категории.

Форма

from wtforms.ext.sqlalchemy.fields import QuerySelectField  #import the ext.

def enabled_topics(): # query the topics (a.k.a categories)
    return Topic.query.all()

class PostForm(Form):  # create your form
    title = StringField(u'title', validators=[DataRequired()])
    body = StringField(u'Text', widget=TextArea())
    topic = QuerySelectField(query_factory=enabled_topics, allow_blank=True)

Модели Важной частью здесь является а) проверка правильности определения взаимосвязи и б) добавление темы в ваш init, поскольку вы используете ее для создания новой записи.

class Post(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    title = db.Column(db.String(80))
    body = db.Column(db.Text)
    # one-to-many with Topic
    topic = db.relationship('Topic', backref=db.backref('post', lazy='dynamic'))

def __init__(self, title, body, topic):
        self.title = title
        self.body = body
        self.topic = topic

class Topic(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(50))

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

Вид Здесь нет ничего особенного.Просто обычное представление, которое генерирует форму и обрабатывает отправленные результаты.

@app.route('/create', methods=['GET', 'POST'])
@login_required
def create_post():
    form = PostForm()
    if form.validate_on_submit():
        post = Post(title=form.title.data, body=form.body.data,
                    topic=form.topic.data)
        db.session.add(post)
        db.session.commit()
        Topic.update_counts()
        flash('Your post has been published.')
        return redirect(url_for('display_post', url=url))
    posts = Post.query.all()
    return render_template('create_post.html', form=form, posts=posts)

шаблон Здесь тоже нет ничего особенного.Просто не забудьте отобразить поле в шаблоне так, как вы бы отображали базовое поле.Никакого сложного цикла не требуется, поскольку расширения WTForms Sqlalchemy делают все это за вас.

{% extends "base.html" %}
{% block title %}Create/Edit New Post{% endblock %}
{% block content %}
<H3>Create/Edit Post</H3>
<form action="" method=post>
   {{form.hidden_tag()}}
   <dl>
      <dt>Title:
      <dd>{{ form.title }}
      <dt>Post:
      <dd>{{ form.body(cols="35", rows="20") }}
      <dt>Topic:
      <dd>{{ form.topic }}
   </dl>
   <p>
      <input type=submit value="Publish">
</form>
{% endblock %}

Вот и все!Теперь в моей форме публикации есть выпадающий список тем.Используя вашу терминологию, когда вы загружаете транзакцию, категория по умолчанию для этой транзакции будет выделена в выпадающем списке.Правильный способ заявить об этом - сказать, что категория, связанная с транзакцией, загружается через отношение, определенное в модели trans.

Также обратите внимание, что существует также расширение multisellect SQLAlchemy на случай, если одна транзакция имеет много категорий по умолчанию.

Теперь моя проблема заключается в том, как справляться с отношениями "многие ко многим"....Я пытаюсь передать строку тегов, которые хранятся в таблице "многие ко многим", в поле TextArea.Для этого нет расширения SQLAlchemy!

Я опубликовал этот вопрос здесь

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top