【问题标题】:pass a parameter to a view function (form) in a for loop to populate form flask wtforms sqlalchemy将参数传递给 for 循环中的视图函数(表单)以填充表单烧瓶 wtforms sqlalchemy
【发布时间】:2019-11-16 19:01:44
【问题描述】:

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

@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>

在谷歌开发者工具上,每个表单都显示 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 code”的类似错误

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

我改成了:

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

这给了我以下错误:

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

【问题讨论】:

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


    【解决方案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")
    

    【讨论】:

    • 嗨@Greg Cowell,谢谢您的回复,我已经修改了您的代码,但我的问题中显示了一个错误,这是因为“base.html”导航中的此页面链接bar 需要 ['id'],此时我不想给出。
    • 我认为您需要为页面提供一个大表单。表单代码需要为每个模型的记录动态生成字段。然后,您的表单 HTML 模板将需要遍历字段列表,以便显示它们。我的示例代码将帮助您从视图代码中预填充表单字段。
    • 查看 FieldList 类,了解如何为所有模型的记录构建单个大型表单。
    • 嗨,谢谢你回来找我,是的,我可以通过在主页上显示行来做到这一点,每个行都有一个链接来打开编辑页面,但作为捷径我是希望我可以在一个页面(带有分页)上显示每一行的表格,然后可以在同一页面上快速编辑。这个应用程序是我在本地网络上托管的业务的会计数据库,我希望有一个页面显示每笔交易,其中每笔交易都是可更新的形式“grande livre”或总账。在我使用 libre office base 的那一刻,我想尝试将其复制为可访问的网络应用程序。
    • 如果我正确理解您的要求,您希望将所有记录显示在一个页面上,并使用表单字段就地编辑它们。您可以选择 1. 一个带有单个提交按钮的大型动态生成表单。 2. 一个页面,每个记录都有一个表单,每个记录都有一个单独的提交按钮。我相信你想要选项 2。请确认,我会给你一些关于如何处理它的建议。
    【解决方案2】:

    要制作一个 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 %}
    

    我在这个 repo 中放了一个完整的例子:Example of multiple forms on a single page

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-06-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-09-26
      • 2021-12-29
      • 1970-01-01
      • 2018-04-03
      相关资源
      最近更新 更多