使用烧瓶逐步展示演示

Posted

技术标签:

【中文标题】使用烧瓶逐步展示演示【英文标题】:Showing demo step by step with flask 【发布时间】:2021-07-25 20:06:40 【问题描述】:

我想展示一个我在 Python 中使用 Flask 编写的函数的演示。我有一个分配给变量的不同输入和输出的示例列表。 所以我想遍历列表,并在单个页面中单独显示每个示例。提示用户是否想查看如何获得答案的详细说明。并且有两个按钮,我们称它们为“是”和“否”。 如果按下“是”,则会显示一些额外的信息。最后,应该有一个“下一步”按钮,其作用与“否”相同(如下所述) 如果“否”,那么我想继续列表中的下一个示例。

这是怎么做到的?

在我的 *.py 文件中:

@app.route('/demo', methods = ["GET", "POST"])
def demo():
   examples = [[first example stuff],[second...], ... ]
   for index in range(0, len(examples)):
        example = examples[index]
        if 'yes' in request.form:
           return render_template('demo.html', example=example, answer=True)
        elif 'no' in request.form:
           pass  # Continue with demo
        return render_template('demo.html', example=example, answer=False)

在我的 demo.html 模板中:

    example 

   <p>Do you want to see how the answer was reached?</p>
   <form method = "post">
      <input type = "submit" name = "yes" value = "Sure!">
      <input type = "submit" name = "no"  value = "No, thanks">
   </form>

   % if answer %
      <!--show extra info -->
   (% endif %

这行不通,我只是不知道该怎么做。 我查看了这些链接,但不知道该怎么做:

https://www.codegrepper.com/code-examples/python/how+to+add+next+button+in+flask

How to implement a next button in flask?

谢谢!

【问题讨论】:

使用for-loop 是完全错误的想法。当您按下按钮时,它会再次运行demo(),因此它会再次启动for-loop,它只获得第一个示例。您的按钮应发送当前示例的编号,demo() 应使用此编号获取正确示例的数据 只需在demo() 中使用print() 来显示变量中的值,您会发现这是错误的想法。 也许可以代替&lt;form&gt; 使用普通的&lt;a&gt;/demo/1 demo/2 甚至/demo/1/yes demo/2/no 之类的链接 - 或在&lt;form&gt; 添加带有演示编号的字段 你的 elif ...: pass 没用 - 你可以删除它,代码也能正常工作。 【参考方案1】:

for-loop 是完全错误的想法。

当您按下按钮时,它会从头开始运行demo,然后从头开始再次运行for-loop,因此它总是得到第一个示例。

您应该将示例编号放在form 中作为隐藏字段

<input type="hidden" name="number" value=" example_number "/>

当你按下按钮时从form获取它

def demo():

    number = request.form.get('number', 0) # as default it will use `0`
    number = int(number)

    button = request.form.get('btn')

首先您可以使用number 和按钮nextprevious 来更改它

    if button == 'NEXT':
        if number < len(examples)-1:
            number += 1

    if button == 'PREV':
        if number > 0:
            number -= 1

稍后您可以使用number 从列表中获取正确的示例

    text = examples[number][0]
    if button == 'YES':
        help = examples[number][1]
    else:
        help = None

最小的工作示例。

我使用两种形式使其更具可读性。

from flask import Flask, request, render_template_string

examples = [("Hello", "It is first help"), ("World", "It is second help")]

app = Flask(__name__)

@app.route('/', methods=['GET', 'POST'])
def index():
    
    number = request.form.get('number', 0) # as default it will use `0`
    number = int(number)
    
    button = request.form.get('btn')

    print('number before:', number)
    
    if button == 'NEXT':
        if number < len(examples)-1:
            number += 1

    if button == 'PREV':
        if number > 0:
            number -= 1
            
    text = examples[number][0]
    if button == 'YES':
        help = examples[number][1]
    else:
        help = None
    
    print('number after :', number)
    print('text:', text)
    print('help:', help)
    
    return render_template_string('''
Text:  text 
% if help %<br>Help:  help  % endif %

<form method="POST">
<input type="hidden" name="number" value=" example_number "/>
<button type="submit" name="btn" value="YES">YES</button>
<button type="submit" name="btn" value="NO">NO</button>
</form>

<!-- other elements  -->

<form method="POST">
<input type="hidden" name="number" value=" example_number "/>
<button type="submit" name="btn" value="PREV">PREV</button>
<button type="submit" name="btn" value="NEXT">NEXT</button>
</form>
''', example_number=number, text=text, help=help)


if __name__ == '__main__':
    #app.debug = True 
    app.run() 

【讨论】:

【参考方案2】:

您的价值是是和否,谢谢,所以我们可以删除不必要的东西。

  <input type = "submit" name = "yes" value = "Sure!">
  <input type = "submit" name = "no"  value = "No, thanks"


@app.route('/demo', methods = ["GET", "POST"])
def demo():
   examples = [[first example stuff],[second...], ... ]
   for example in examples:
        if request.form.get('yes') is not None:
           return render_template('demo.html', example=example, answer=True)
        elif request.form.get('no') is not None:
           pass  
        return render_template('demo.html', example=example, answer=False)

【讨论】:

【参考方案3】:

这就是我最终的做法。

在我的python文件中:

index :int
# I decided to put the steps as a global list, so that it doesn't assign it to the variable
# each time that demo() and step_by_step() are called, and so that I don't need to pass as argument
demo_steps = [...]

# demo just calls step_by_step(), but it always starts from 0
# So when user clicks on "demo" in navigator link, the demo restarts
@app.route('/demo')
def demo():
    global index
    index = 0
    return redirect(url_for('step_by_step', step=index))
    step_by_step(index)

@app.route('/demo/<int:step>', methods = ["GET", "POST"])
def step_by_step(step):
    global index, demo_steps
    index = min(step, len(demo_steps)-1)  # to prevent a user from typing "/demo/20" (for example) in the URL
    short_answer = demo_steps[index][0]
    detailed_answer = demo_steps[index][1]

    if request.method == "POST":
        if 'yes' in request.form:
            return render_template('demo.html',
                                   short = short_answer,
                                   detailed = detailed_answer,
                                   show_answer = True)
        # user clicked 'no' ( = doesn't want detailed explanation),
        # or 'next' (after seeing the detailed explanation)
        # Either way, we move to the next step in the demo
        elif 'no' or 'next' in request.form:
            index += 1
            if index < len(demo_steps):
                return redirect(url_for('step_by_step', step=index))
                step_by_step(index)
            else:
                return redirect(url_for('finished'))
    elif request.method == "GET":
        return render_template('demo.html',
                   short = short_answer,
                   detailed = detailed_answer,
                   show_answer = False)

@app.route('/finished')
def finished():
    return render_template('finished.html') # A simple page saying demo is finished

在我的 demo.html 模板中:

<h1>The short answer is:  short </h1>

<p>Do you want to see how the answer was reached?</p>
<form method = "post">
    <input type = "submit" name = "yes" value = "Sure!">
    <input type = "submit" name = "no"  value = "No, thanks">
</form>

% if show_answer %
    <h3>These are the steps that the program took to find the answer</h3>
    % for step in detailed %
        <li> step </li>
    % endfor %
    <p></p>
    <form method = "post">
        <input type = "submit" name = "next" value = "Continue">
    </form>
% endif %

【讨论】:

以上是关于使用烧瓶逐步展示演示的主要内容,如果未能解决你的问题,请参考以下文章

Kubernetes 入口烧瓶应用程序

使用 ngrok 部署烧瓶应用程序时出现错误索引

sql 这些代码片段将演示如何逐步使用PolyBase。你应该有一个blob存储和存储秘密方便

β版本成果展示和使用实例-第二组攻城喵组

python 这演示了如何逐步计算python生成器的线性回归,以避免需要加载整个结构

展示C代码覆盖率的gcovr工具简单介绍及相关命令使用演示样例