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