在for循环中将参数传递给视图函数(窗体)以填充窗体flask wtforms sqlalchemy

时间:2019-11-16 19:01:44

标签: python-3.x flask flask-sqlalchemy flask-wtforms

我希望能够以可更新的预填充形式在我的网页上显示数据库模型的行!我可以轻松显示页面上的行,也可以为每个行添加链接以打开单独的页面来编辑每一行,也可以使用更新表单显示每一行,但是无法显示填充的表单。这是我的代码:

@bp.route('/stock', methods=['GET', 'POST'])
@bp.route('/stock/<int:id>', methods=['GET', 'POST'])
@login_required
def stock(id=None):
    if id is not None:
        obj = Stock.query.get_or_404(id)
        form = AddStockForm(request.form, obj=obj)
        if form.validate_on_submit():
            form.populate_obj(obj)
            db.session.commit()
        return redirect(url_for('stock.stock'))
    else:
        form = AddStockForm()
        page = request.args.get('page', 1, type=int)
        stock = Stock.query.order_by(Stock.id.desc()).paginate(
        page, current_app.config['ITEMS_PER_PAGE'], False)
        next_url = url_for('stock.stock', page=stock.next_num) \
            if stock.has_next else None
        prev_url = url_for('stock.stock', page=stock.prev_num) \
            if stock.has_prev else None
        return render_template('stock/stock.html',form=form, title=Stock, stock=stock.items,
             next_url=next_url, prev_url=prev_url)

和stock.html代码:

{% extends "base.html" %}

{% block content %}
<div class="main">
    <h2>Stock</h2>
    <div class="books"><a href="{{ url_for('stock.upload_stock') }}">Upload Stock csv</a> 
</div>
    <div class="books"><a href="{{ url_for('stock.add_stock') }}">Add a new Item</a></div>
    {% for s in stock %}
        {% include 'stock/_stock.html' %}
    {% endfor %}
</div>

_stock.html代码:

<div class="stock">
    <div class="c0"><img src="{{ s.image_url }}" alt="{{ s.image_filename }}"></div>

        <form action="{{ url_for('stock._stock', id=s.id) }}" method="post", 
           enctype="multipart/form-data">
            {{ form.hidden_tag() }}
            <div>SKU<BR> {{ s.id }} </div>
            <div>Date of Purchase<br>{{ form.date(class="input") }}</div>
            <div>Description<br>{{ form.description(class="input") }}</div>
            <div>Market<br>{{ form.event(class="input") }}</div>
            <div>Purchase Price<br>{{ form.achat(class="input") }}</div>
            <div>Sale Price<br>{{ form.vente(class="input") }}</div>
            <div>Sold<br>{{ form.sold(class="input") }}</div>
            <div>{{ form.submit(class="submit") }}</div>
        </form>

</div>

在Google开发人员工具上,每个表单都显示stock / 4或3,但这似乎并未填充表单。没有错误消息。 在此先感谢您的帮助。 问候保罗

编辑 @Greg Cowell,您好,谢谢您的帮助,我已经修改了您的代码,但是出现此错误

  File "/var/www/accounts/bdf/templates/base.html", line 30, in root
</body>
  File "/var/www/accounts/env/lib/python3.7/site-packages/jinja2/runtime.py", line 262, in call
return __obj(*args, **kwargs)
  File "/var/www/accounts/env/lib/python3.7/site-packages/flask/helpers.py", line 370, in url_for
return appctx.app.handle_url_build_error(error, endpoint, values)
  File "/var/www/accounts/env/lib/python3.7/site-packages/flask/app.py", line 2215, in handle_url_build_error
reraise(exc_type, exc_value, tb)
  File "/var/www/accounts/env/lib/python3.7/site-packages/flask/_compat.py", line 39, in reraise
raise value
  File "/var/www/accounts/env/lib/python3.7/site-packages/flask/helpers.py", line 358, in url_for
endpoint, values, method=method, force_external=external
  File "/var/www/accounts/env/lib/python3.7/site-packages/werkzeug/routing.py", line 2020, in build
raise BuildError(endpoint, values, method, self)
werkzeug.routing.BuildError: Could not build url for endpoint 'stock.stock'. Did you forget to specify values ['id']?
[pid: 29588|app: 0|req: 1/1] 192.168.0.13 () {48 vars in 1095 bytes} [Sun Nov 17 09:26:58 2019] GET /index =>

这是改编的代码:

@bp.route('/stock/stock/<int:id>/', methods=['GET', 'POST'])
@login_required
def stock(id=None):
    if id is not None:
        group = current_user.group()
        try:
            stock = Stock.query.filter_by(group=group, id=id).one()
        except NoResultFound:
            flash('Invalid account.')
            return redirect(url_for('stock.add_stock'))
        accounts = current_user.group().stock
        form = AddStockForm()
        form.stock_id.default = stock.id
        if form.validate_on_submit():
            if form.modify.data:
                for s in stock:
                    if (
                        item.id == form.stock_id.data and
                        item.id != form.stock_id.default
                    ):
                        flash('Another account already has this name.')
                        return redirect(url_for('stock.add_stock', id=id))
                stock.id = form.stock_id.data
                db.session.add(stock)
            db.session.commit()
        form.process()  # Do this after validate_on_submit or breaks CSRF token
    else:
        form = AddStockForm()
        page = request.args.get('page', 1, type=int)
        stock = Stock.query.order_by(Stock.id.desc()).paginate(
             page, current_app.config['ITEMS_PER_PAGE'], False)
        next_url = url_for('stock.stock', page=stock.next_num) \
            if stock.has_next else None
        prev_url = url_for('stock.stock', page=stock.prev_num) \
            if stock.has_prev else None
    return render_template('stock/stock.html',form=form, title=Stock, stock=stock.items,
         next_url=next_url, prev_url=prev_url)

第二编辑

我将其添加到视图功能的顶部:

@bp.route('/stock', methods=['GET', 'POST'])

摆脱了上面的错误,然后我对于“ stock.html代码”也遇到了类似的错误

    {% for s in stock %}
        {% include 'stock/_stock.html' %}
    {% endfor %}

我改为:

   {% include {{ url_for('stock._stock', id=['s.id']) }} %}

这给了我以下错误:

jinja2.exceptions.TemplateSyntaxError: expected token ':', got '}'

2 个答案:

答案 0 :(得分:1)

我使用另一种方法来预填充表单。

总而言之,我为每个表单字段设置默认值,并在呈现之前处理表单。在下面的示例中,我使用form.account_name.default = account.accname设置account_name字段的默认值,然后在呈现表单之前调用form.process()

@web.route('/accounts/modify/<int:accno>/', methods=['GET', 'POST'])
@login_required
def modify_account(accno):
    """
    Modify or delete accounts.
    Return a form for modifying accounts or process submitted
    form and redirect to Accounts HTML page.
    """
    group = current_user.group()
    try:
        account = Account.query.filter_by(group=group, accno=accno).one()
    except NoResultFound:
        flash('Invalid account.')
        return redirect(url_for('.accounts_page'))
    accounts = current_user.group().accounts
    form = ModifyAccountForm()
    form.account_name.default = account.accname

    if form.validate_on_submit():
        if form.modify.data:
            for item in accounts:
                if (
                    item.accname == form.account_name.data and
                    item.accname != form.account_name.default
                ):
                    flash('Another account already has this name.')
                    return redirect(url_for('.modify_account', accno=accno))
            account.accname = form.account_name.data
            db.session.add(account)
            db.session.commit()
        elif form.delete.data:
            for transaction in current_user.group().transactions:
                if transaction.account == account:
                    unknown_account = Account.query.filter_by(
                        group=current_user.group(), accname='Unknown').one()
                    transaction.account = unknown_account
                    db.session.add(transaction)
                    db.session.commit()
            db.session.delete(account)
            db.session.commit()
        elif form.cancel.data:
            pass
        return redirect(url_for('.accounts_page'))

    form.process()  # Do this after validate_on_submit or breaks CSRF token

    return render_template(
        'modify_account.html', form=form, accno=accno, menu="accounts")

答案 1 :(得分:1)

要制作一个HTML页面,其中每个记录都有一个表单,每个记录都有一个提交按钮,您需要在视图/路由功能中创建多个表单,然后在HTML模板中循环浏览所有表单。

查看/路线:

@web.route('/stocks', methods=['GET', 'POST'])
def stocks():
    """Return Stocks HTML page."""
    stocks = Stock.query.all()
    forms = []
    for stock in stocks:
        form = ModifyStockForm()
        form.stock_id.default = stock.stock_id
        form.stock_name.default = stock.stock_name
        forms.append(form)

    for form in forms:
        if form.validate_on_submit():
            if form.modify.data:
                stock = Stock.query.filter_by(stock_id=form.stock_id.data).one()
            stock.stock_name = form.stock_name.data
            db.session.add(stock)
            db.session.commit()
        elif form.delete.data:
            stock = Stock.query.filter_by(stock_id=form.stock_id.data).one()
            db.session.delete(stock)
            db.session.commit()
        return redirect(url_for('.stocks'))

        form.process()  # Do this after validate_on_submit or breaks CSRF token

return render_template('stocks.html', forms=forms, stocks=stocks)

模板:

<h2>Stocks:</h2>

   {% for form in forms %}

    <form method="post" role="form" enctype="multipart/form-data">
        {{ form.hidden_tag() }}

        {{ form.stock_id }}
        {{ form.stock_name }}
        {{ form.modify }}
        {{ form.delete }}

    </form>

   {% endfor %}

我已在此仓库中提供了完整的示例:Example of multiple forms on a single page