首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >从多个表创建具有选择项的烧瓶表单

从多个表创建具有选择项的烧瓶表单
EN

Stack Overflow用户
提问于 2014-03-12 21:45:55
回答 1查看 7.6K关注 0票数 2

我看到了大量的教程,这些教程用烧瓶和flash-wtf显示登录表单,但没有从数据库表值中填充多个选择框。

这就是我想要做的:

简单的登记表:

名字 姓 地址行1 地址行2 城市 状态Id (从州库查询Id,state) 国家Id (从国家图书馆查询国家,id)

我们将非常感谢示例代码或遍历的链接。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-03-15 10:53:23

我试图找一个解释如何做这件事,但找不到一个。所以我要在这里写一个。这就是我做事的方式,也许有更好的方法。

源代码

您可以在我的github帐户上下载本教程的完整源代码。 --我基本上是在复制和粘贴源代码,但为了防止github有一天死了,我们来了。

配置

需要配置我们的应用程序和数据库连接。在大多数情况下,您可能希望从配置文件加载所有这些。

在本教程中,我们将使用一个基本的sqlalchemy测试数据库。

代码语言:javascript
运行
复制
app = Flask(__name__)
app.config['SECRET_KEY'] = 'Insert_random_string_here'

如果希望看到生成的所有SQL,请将此配置设置为True。

代码语言:javascript
运行
复制
app.config['SQLALCHEMY_ECHO'] = False
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:////tmp/test.db'

WTForms配置字符串

代码语言:javascript
运行
复制
app.config['WTF_CSRF_ENABLED'] = True

CSRF令牌很重要。在这里阅读更多关于他们的信息,板材

代码语言:javascript
运行
复制
app.config['WTF_CSRF_SECRET_KEY'] = 'Insert_random_string_here'
db = SQLAlchemy(app)

SQLALchemy模型

接下来,我们需要创建我们的模型类,这些类将在创建数据库期间以及当我们想要操作数据库时使用。这通常应该是它自己独立的文件。

我从这里要挟,好像这是自己的独立文件。

通常,您必须从应用程序导入db执行类似的操作。

代码语言:javascript
运行
复制
class RegisteredUser(db.Model):
    """
    loads and pushes registered user data after they have signed up.

    SQLalchemy ORM table object which is used to load, and push, data from the
    server memory scope to, and from, the database scope.
    """
    __tablename__ = "RegisteredUser"

    #all of the columns in the database.
    registered_id = db.Column(db.Integer, primary_key=True)
    first_name = db.Column(db.String(70))
    last_name = db.Column(db.String(70))
    address_line_one = db.Column(db.String(256))
    address_line_two = db.Column(db.String(256))
    city = db.Column(db.String(50))

    """
    Now we're going to create all of the foreign keys for the RegisteredUser
    table. The db.relationship section allows us to easily and automatically
    join the other tables with registeredUser. The Join will only take place
    if you attempt to access columns from the State or country table.

    For more on Foreign keys using SQLAlchemy go to
    """
    state_id = db.Column(
            db.Integer,
            db.ForeignKey('State.state_id'),
            nullable=False)
    #retrives the users name for display purposes.
    state_by = db.relationship(
            'State',
            foreign_keys=[state_id],
            backref=db.backref('State', lazy='dynamic'))
    country_id = db.Column(
            db.Integer,
            db.ForeignKey('Country.country_id'),
            nullable=False)
    #retrives the users name for display purposes.
    country_by = db.relationship(
            'Country',
            foreign_keys=[country_id],)

    #this is the method and function style I've chosen when lines are too long
    def __init__(
            self,
            first_name,
            last_name,
            address_line_one,
            address_line_two,
            city,
            state_id,
            country_id):
        """
        Used to create a RegisteredUser object in the python server scope

        We will be calling these init functions every time we use
        RegisteredUser() as a 'function' call. It will create a SQLalchemy ORM
        object for us.
        """
        self.first_name = first_name
        self.last_name = last_name
        self.address_line_one = address_line_one
        self.address_line_two = address_line_two
        self.city = city
        self.state_id = state_id
        self.country_id = country_id


class State(db.Model):  # pylint: disable-msg=R0903
    """
    Holds State names for the database to load during the registration page.

    SQLalchemy ORM table object which is used to load, and push, data from the
    server memory scope to, and from, the database scope.
    """
    __tablename__ = "State"

    state_id = db.Column(db.Integer, primary_key=True)
    state_name = db.Column(db.String(10), unique=True)

    def __init__(self, state_name):
        """
        Used to create a State object in the python server scope
        """
        self.state_name = state_name


class Country(db.Model):  # pylint: disable-msg=R0903
    """
    Holds Country names for the database to load during the registration page.

    SQLalchemy ORM table object which is used to load, and push, data from the
    server memory scope to, and from, the database scope.
    """
    __tablename__ = "Country"

    country_id = db.Column(db.Integer, primary_key=True)
    #longest country length is currently 163 letters
    country_name = db.Column(db.String(256), unique=True)

    def __init__(self, country_name):
        """
        Used to create a Country object in the python server scope
        """
        self.country_name = country_name


def create_example_data():
    """
    Generates all of the demo data to be used later in the tutorial. This is
    how we can use our ORM objects to push data to the database.

    NOTE: create_example_data is called at the very bottom of the file.
    """
    #Create a bunch of state models and add them to the current session.
    #Note, this does not add rows to the database. We'll commit them later.
    state_model = State(state_name="WA")
    db.session.add(state_model)
    state_model = State(state_name="AK")
    db.session.add(state_model)
    state_model = State(state_name="LA")
    db.session.add(state_model)
    #Normally I load this data from very large CVS or json files and run This
    #sort of thing through a for loop.

    country_model = Country("USA")
    db.session.add(country_model)
    country_model = Country("Some_Made_Up_Place")
    db.session.add(country_model)
    # Interesting Note: things will be commited in reverse order from when they
    # were added.
    try:
        db.session.commit()
    except IntegrityError as e:
        print("attempted to push data to database. Not first run. continuing\
                as normal")

WTForm

现在我们将制作我们的WTForms对象。这些文件将从数据库中获取数据,然后将它们传递到模板文件中,在那里我们将呈现它们。

我从这里要挟,好像这是自己的独立文件。

代码语言:javascript
运行
复制
import wtforms
import wtforms.validators as validators
from flask.ext.wtf import Form

class RegistrationForm(Form):
    """
    This Form class contains all of the fileds that make up our registration
    Form. 
    """
    #Get all of the text fields out of the way.
    first_name_field = wtforms.TextField(
            label="First Name",
            validators=[validators.Length(max=70), validators.Required()])
    last_name_field = wtforms.TextField(
            label="Last Name",
            validators=[validators.Length(max=70), validators.Required()])
    address_line_one_field = wtforms.TextField(
            label="Address",
            validators=[validators.Length(max=256), validators.Required()])
    address_line_two_field = wtforms.TextField(
            label="Second Address",
            validators=[validators.Length(max=256), ])
    city_field = wtforms.TextField(
            label="City",
            validators=[validators.Length(max=50), validators.Required()])
    # Now let's set all of our select fields.
    state_select_field = wtforms.SelectField(label="State", coerce=int)
    country_select_field = wtforms.SelectField(label="Country", coerce=int)

视图

进口瓶

代码语言:javascript
运行
复制
def populate_form_choices(registration_form):
    """
    Pulls choices from the database to populate our select fields.
    """
    states = State.query.all()
    countries = Country.query.all()
    state_names = []
    for state in states:
        state_names.append(state.state_name)
    #choices need to come in the form of a list comprised of enumerated lists
    #example [('cpp', 'C++'), ('py', 'Python'), ('text', 'Plain Text')]
    state_choices = list(enumerate(state_names))
    country_names = []
    for country in countries:
        country_names.append(country.country_name)
    country_choices = list(enumerate(country_names))
    #now that we've built our choices, we need to set them.
    registration_form.state_select_field.choices = state_choices
    registration_form.country_select_field.choices = country_choices

@app.route('/', methods=['GET', 'POST'])
def demonstration():
    """
    This will render a template that displays all of the form objects if it's
    a Get request. If the use is attempting to Post then this view will push
    the data to the database.
    """
    #this parts a little hard to understand. flask-wtforms does an implicit
    #call each time you create a form object. It attempts to see if there's a
    #request.form object in this session and if there is it adds the data from
    #the request to the form object.
    registration_form = RegistrationForm()
    #Before we attempt to validate our form data we have to set our select
    #field choices. This is just something you need to do if you're going to 
    #use WTForms, even if it seems silly.
    populate_form_choices(registration_form)
    #This means that if we're not sending a post request then this if statement
    #will always fail. So then we just move on to render the template normally.
    if flask.request.method == 'POST' and registration_form.validate():
        #If we're making a post request and we passed all the validators then
        #create a registered user model and push that model to the database.
        registered_user = RegisteredUser(
            first_name=registration_form.data['first_name_field'],
            last_name=registration_form.data['last_name_field'],
            address_line_one=registration_form.data['address_line_one_field'],
            address_line_two=registration_form.data['address_line_two_field'],
            city=registration_form.data['city_field'],
            state_id=registration_form.data['state_select_field'],
            country_id=registration_form.data['country_select_field'],)
        db.session.add(registered_user)
        db.session.commit()
        return flask.render_template(
            template_name_or_list='success.html',
            registration_form=registration_form,)
    return flask.render_template(
            template_name_or_list='registration.html',
            registration_form=registration_form,)

runserver.py

最后,这仅用于开发目的。我通常把它放在一个名为RunServer.py的文件中。为了实际交付应用程序,您应该在某种web服务器(Apache、Nginix、Heroku)后面运行。

代码语言:javascript
运行
复制
if __name__ == '__main__':
    db.create_all()
    create_example_data()
    app.run(debug=True)

模板

在macros.html中

代码语言:javascript
运行
复制
{% macro render_field(field) %}
  <dt>{{ field.label }}
  <dd>{{ field(**kwargs)|safe }}
  {% if field.errors %}
    <ul class=errors>
    {% for error in field.errors %}
      <li>{{ error }}</li>
    {% endfor %}
    </ul>
  {% endif %}
  </dd>
{% endmacro %}

{% macro render_data(field) %}
  <dt>{{ field.label }}
  <dd>{{ field.data|safe }}
  {% if field.errors %}
    <ul class=errors>
    {% for error in field.errors %}
      <li>{{ error }}</li>
    {% endfor %}
    </ul>
  {% endif %}
  </dd>
{% endmacro %}

在registration.html中

代码语言:javascript
运行
复制
{% from "macros.html" import render_field %}
<form method=post action="/">
    {{registration_form.hidden_tag()}}
  <dl>
    {{ render_field(registration_form.first_name_field) }}
    {{ render_field(registration_form.last_name_field) }}
    {{ render_field(registration_form.address_line_one_field) }}
    {{ render_field(registration_form.address_line_two_field) }}
    {{ render_field(registration_form.city_field) }}
    {{ render_field(registration_form.state_select_field) }}
    {{ render_field(registration_form.country_select_field) }}
  </dl>
  <p><input type=submit value=Register>
</form>

最后,在success.html中

代码语言:javascript
运行
复制
{% from "macros.html" import render_data %}
<h1> This data was saved to the database! </h1>
<form method=post action="/">
    {{registration_form.hidden_tag()}}
  <dl>
    {{ render_data(registration_form.first_name_field) }}
    {{ render_data(registration_form.last_name_field) }}
    {{ render_data(registration_form.address_line_one_field) }}
    {{ render_data(registration_form.address_line_two_field) }}
    {{ render_data(registration_form.city_field) }}
    {{ render_data(registration_form.state_select_field) }}
    {{ render_data(registration_form.country_select_field) }}
  </dl>
  <p><input type=submit value=Register>
</form>
票数 12
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/22364551

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档