Python Flask:将Jinja变量传递给后端

时间:2018-07-25 08:41:50

标签: python flask

我有一个简单的Flask Web应用程序,其中显示了我从TSV文件(使用Pandas)读取的表格。对于每一行,我正在显示索引,一些文本,一个标签(正/负),一个日期和一个“更改标签”按钮。

我希望能够在TSV文件中为单击“更改标签”按钮的特定文本更改标签。我当时在考虑使用/edit/<index>这样的URL,以便可以使用URL中传递的索引在TSV中找到相应的行并进行更改,但是没有运气。

例如,当我单击表第一行中的“更改标签”按钮时,URL为/edit/0

这就是我所拥有的。

Python Flask应用

@app.route('/admin', methods=['GET', 'POST'])
def admin():
    if request.method == 'GET':  
        return render_template('admin.html')

    if request.method == 'POST':
        if request.form['submit'] == 'Manage':
            from_date = '01-01-1900'
            to_date = '01-01-2900'

            df = pd.read_csv('dataset.tsv', sep='\t', encoding='utf-8')
            indexes = df.index.values.tolist()
            texts = df['text'].values.tolist()
            labels = df['label'].values.tolist()
            dates = df['date'].values.tolist()
            data = zip(indexes, texts, labels, dates)

        return render_template('admin.html', from_date=from_date, to_date=to_date, data=data)

@app.route('/edit/<id>', methods=['GET', 'POST'])
def edit():
    if request.method == 'GET':
        return render_template('admin.html')

    if request.method == 'POST':
        # TODO, open TSV file and change label
        return render_template('admin.html')

admin.html

<!doctype html>
<head>
    <link rel="stylesheet" media="screen" href ="static/bootstrap.min.css">
    <link rel="stylesheet" href="static/bootstrap-theme.min.css">
    <meta name="viewport" content = "width=device-width, initial-scale=1.0">
</head>

<div class="container">
    <table class="table">
        <thead>
            <tr>
                <th scope="col">#</th>
                <th scope="col">Text</th>
                <th scope="col">Label</th>
                <th scope="col">Date</th>
                <th scope="col">Edit</th>
            </tr>
        </thead>
        <tbody>
            {% for index, text, label, date in data %}
            <tr>
                <th>{{ index }}</th>
                <th>{{ text }}</th>
                <th>{{ label }}</th>
                <th>{{ date }}</th>
                <th>
                    <form action="/edit/{{ index }}" method="post" role="form">
                        <input type="submit" name="submit" value="Change Label" class="btn btn-info">
                    </form>
                </th>
            </tr>
            {% endfor %}
        </tbody>
    </table>
</div>
</html>

我知道问题与<form action="/edit/{{ index }}" method="post" role="form">中的admin.html有关,因为它无法传递URL中的索引。当我单击任何按钮时,它会将我重定向到/edit/,而没有任何索引。可以通过某种方式在URL中传递变量{{ index }}还是应该以其他方式完成?

2 个答案:

答案 0 :(得分:1)

对于这种任务,我建议您使用url_for。

我认为这是首选方法,因为它可以让您构建有意义且始终有效的URL,而不必依赖用户表单。

例如,如果您决定制作一个API或用户决定共享书签以便快速实现Web应用程序中的特定功能,这将对您大有帮助。

这是documentation中的一个相关示例(如果您想了解更多内容,请查看URL Building):

from flask import Flask, url_for

app = Flask(__name__)

@app.route('/')
def index():
    return 'index'

@app.route('/login')
def login():
    return 'login'

@app.route('/user/<username>')
def profile(username):
    return '{}\'s profile'.format(username)

with app.test_request_context():
    print(url_for('index'))
    print(url_for('login'))
    print(url_for('login', next='/'))
    print(url_for('profile', username='John Doe'))

这也是如何从small app I wrote编写模板的示例(它具有基本的CRUD功能,因此您可能会发现它很有用):

<div data-role="content">
    <h3 class="center">Edit restaurant</h3>
    <label for="textinput-hide" class="ui-hidden-accessible">Text Input:</label>
    <form id="new-restaurant-form" action="{{url_for('edit_restaurant', restaurant_id=restaurant.id)}}" method="POST" target="_parent">
    <input type="text" name="restaurant-name" id="textinput-hide" placeholder="{{restaurant.name}}" value="">
    <fieldset class="ui-grid-a">
        <div class="ui-block-a"><a href="#" data-role="button" data-rel="back" data-theme="c">Cancel</a></div>
        <div class="ui-block-b"><button type="submit" data-role="button" data-transition="flow" data-theme="b"
                                   id="btn-add-new-ok">Ok</button></div>
    </fieldset>
    </form>
</div>

答案 1 :(得分:1)

您为什么不利用隐藏的表单输入?在您的表单中,添加隐藏的输入元素:

{% for index, text, label, date in data %}
<tr>
    <th>{{ index }}</th>
    <th>{{ text }}</th>
    <th>{{ label }}</th>
    <th>{{ date }}</th>
    <th>
        <form action="/edit" method="post" role="form">
            <input type="hidden" id="index" name="index" value="{{ index }}">
            <input type="submit" name="submit" value="Change Label" class="btn btn-info">
        </form>
    </th>
</tr>
{% endfor %}

然后在您的路线上

@app.route('/edit', methods=['GET', 'POST'])
def edit():
    if request.method == 'GET':
        return render_template('admin.html')

    if request.method == 'POST':
        index = int(request.form['index'])
        # Now use `index` to change your TSV
        return render_template('admin.html')