Hello, Flask!
首发于Hello, Flask!
Flask实践:猜数字

Flask实践:猜数字

Demo体验:猜数字 - Flask

难度:1

使用扩展:Flask-Bootstrap、Flask-WTF

- - - - -

每个学编程的人大概都写过猜数字游戏,今天我们用Flask来做一个Web版本的猜数字。功能很简单,只有两个路由,三个模板和一个表单组成。扩展的版本见项目的Github页面。

项目结构

|-GuesstheNumber 项目名称
    |-app.py
    |-templates/  模板文件夹
        |-index.html  
        |-guess.html
        |-base.html  基模板
    |-venv/  虚拟环境

实现代码

app.py

# -*- coding: utf-8 -*-
import random

from flask import Flask, render_template, flash, redirect, url_for, session
from flask_wtf import Form
from wtforms import IntegerField, SubmitField
from wtforms.validators import DataRequired, NumberRange
from flask_bootstrap import Bootstrap

app = Flask(__name__)
app.config['SECRET_KEY'] = 'very hard to guess string'  #设置secret key
bootstrap = Bootstrap(app)  # 初始化Flask-Bootstap扩展


@app.route('/')
def index():
    # 生成一个0~1000的随机数,存储到session变量里。
    session['number'] = random.randint(0, 1000)  
    session['times'] = 10
    return render_template('index.html')


@app.route('/guess', methods=['GET', 'POST'])
def guess():
    times = session['times'] # 从session变量里获取次数
    # 从session变量里获取在index函数里生成的随机数字
    result = session.get('number')  
    form = GuessNumberForm()
    if form.validate_on_submit():
        times -= 1
        session['times'] = times  # 更新次数值
        if times < 0:
            flash(u'你输啦……o(>﹏<)o')
            return redirect(url_for('index'))
        answer = form.number.data
        if answer > result:
            flash(u'太大了!你还剩下%s次机会' % times)
        elif answer < result:
            flash(u'太小了!你还剩下%s次机会' % times)
        else:
            flash(u'啊哈,你赢了!V(^-^)V')
            return redirect(url_for('index'))
        return redirect(url_for('guess'))
    return render_template('guess.html', form=form)


class GuessNumberForm(Form):
    number = IntegerField(u'输入数字(0~1000):', validators=[
        # 传入验证函数和相应的错误提示信息。
        DataRequired(u'输入一个有效的数字!'),
        NumberRange(0, 1000, u'请输入0~1000以内的数字!')])
    submit = SubmitField(u'提交')


if __name__ == '__main__':  # 用于heroku部署,本地可省略
    app.run()

index.html

{% extends "base.html" %}

{% block page_content %}
<!-- 传入url_for的参数是视图函数的名称 -->
<a class="btn btn-success btn-lg" href="{{ url_for('guess') }}">开始游戏</a>
{% endblock %}

guess.html

{% extends "base.html" %} <!-- 引入基模板 -->
{% import "bootstrap/wtf.html" as wtf %}

{% block page_content %}
    <!-- 使用Flask-Bootstrap提供的函数来生成默认样式的表单 -->
    {{ wtf.quick_form(form) }}
{% endblock %}

完整的项目见源码(底部)。

相关知识

  • session(会话)

session是Flask的上下文(context)全局变量,可以用来存储(用字典的形式)请求之间需要“记住”的值。在这个猜数字游戏里,我使用它来存储生成的随机数和剩余的机会次数。

要使用session,得先设置一个secret key,这用来给Cookie签名以加密session,这样做的效果是用户可以看到cookie但不能篡改它。尽管如此,session并不是安全的,不能用来存储密码,事实上也不适合用来存储猜数字游戏的答案。我们可以在浏览器看到站点的Cookie信息,其中名为session的cookie就是Flask存入的session内容:

我们可以通过对session的值进行base64获取到其中的内容。最简单的,你可以在JWT.IO提供的解码工具进行测试,示例如下所示。左侧输入的是session的令牌值,右侧为解析后的结果,其中的number即答案:

更多细节见:flask.pocoo.org/docs/0.

安装和运行

源码地址:github.com/helloflask/g

下载或使用git命令克隆项目后,切换到程序根目录。使用virtualenv创建一个虚拟环境,激活后使用pip安装所需依赖:

pip install -r requirements.txt

然后运行:

flask run

访问: 127.0.0.1:5000/

上面的代码实现的效果:

稍微美化一下,变成了下面这样:


源码:github.com/helloflask/g

Demo:guessguess.herokuapp.com

更多关于Flask的优质内容,欢迎关注Hello, Flask! - 知乎专栏

编辑于 2018-07-15

文章被以下专栏收录

    Hello,我是李辉,一个 Python 程序员。在这个专栏,你会看到我学习和使用 Flask 的经验和总结,你还会看到我所有的发明创造,以及它们的实现方法。欢迎加入这场 Flask 之旅,拿好你的小键盘,上车吧!helloflask.com