Python WTForms:使用关系设置SQLAlchemy字段的默认值

Python WTForms:使用关系设置SQLAlchemy字段的默认值,python,sqlalchemy,flask,wtforms,Python,Sqlalchemy,Flask,Wtforms,这里有很多问题,题目听起来与我将要描述的内容相似,但从我几个小时的研究中可以看出,这个问题是独一无二的。好了 我正在写我的第一个烧瓶应用程序。我正在为模型层和WTForms使用SQLAlchemy来处理表单。该应用程序将是一个轻量级的个人理财经理,我可能不会真正用于严肃的业务。我有一个表格用于列出所有交易,另一个表格用于列出所有费用类别(食品杂货、服装等)。事务表有一列(“类别”),该列引用类别表。在视图中,我用一个元素表示类别列表 我的问题是,在编辑事务时,我不知道如何告诉WTForms将元素

这里有很多问题,题目听起来与我将要描述的内容相似,但从我几个小时的研究中可以看出,这个问题是独一无二的。好了

我正在写我的第一个烧瓶应用程序。我正在为模型层和WTForms使用SQLAlchemy来处理表单。该应用程序将是一个轻量级的个人理财经理,我可能不会真正用于严肃的业务。我有一个表格用于列出所有交易,另一个表格用于列出所有费用类别(食品杂货、服装等)。事务表有一列(“类别”),该列引用类别表。在视图中,我用一个元素表示类别列表

我的问题是,在编辑事务时,我不知道如何告诉WTForms将元素设置为特定的预定义值。(是的,我知道您可以在定义表单时设置默认值,这不是我要问的。)

模型如下所示(删除了不相关的字段):

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()])
    # ...
路线(尚未实施POST):

正如您在路由中看到的,我从transaction.category.id设置了form.category.default,但这不起作用。我认为我的问题是在创建表单后设置“默认值”。我不得不这么做,因为模型是通过SQLAlchemy从数据库中获取的。根本原因似乎是form.category是一个对象(由于关系),WTForms似乎无法轻松处理它。我不可能是第一个遇到这个。。。我是否需要修改模型以使其更兼容WTForms?我有什么选择


谢谢

我在评论中提到了这一点。听起来您可能会从使用WTForm的SQLAlchemy扩展中受益。这将为trans表单中的类别创建一个下拉列表

我的示例的用例略有不同。我正在把博客帖子和主题联系起来。也就是说,许多帖子共享一个主题。在您的案例中,许多交易共享一个类别

表格

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)
型号 这里重要的部分是a)确保正确定义了关系,以及b.)将主题添加到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 extensions可以为您完成所有这些

{% 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 %}
{%extends“base.html”%}
{%block title%}创建/编辑新帖子{%endblock%}
{%block content%}
创建/编辑帖子
{{form.hidden_tag()}}
标题:
{{form.title}}
职位:
{{form.body(cols=“35”,rows=“20”)}
主题:
{{form.topic}}

{%endblock%}
就这样!现在我的帖子表单有一个主题下拉列表。要使用您的术语,加载事务时,该事务的默认类别将在下拉列表中突出显示。说明这一点的正确方法是,通过trans模型中定义的关系加载与事务关联的类别

另外请注意,如果一个事务有多个“默认”类别,那么还有一个multisellectsqlalchemy扩展

现在,我的问题是如何处理多对多关系。。。。我试图将存储在多对多表中的一系列标记传递给TextArea字段。没有SQLAlchemy的扩展


我贴出了那个问题

是的,我正在写一篇文章。如何将关系的值传递给字段。你找到答案了吗?不过,在您的情况下,看起来您可能能够使用SQLAlchemy WTForm扩展,它将在下拉列表中显示类别值。你试过了吗?谢谢你QuerySelectField正是我想要的。我能够删除我编写的(试图)做完全相同事情的一堆现有代码。
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)
{% 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 %}