Python如何使用Web框架Flask开发项目

2023-05-14 22:05:47 框架 如何使用 开发项目

一、简介

flask是一个轻量级的基于pythonWEB框架

这份文档中的代码使用 Python 3 运行。
建议在 linux 下实践本教程中命令行操作、执行代码。

二、安装

通过pip3安装Flask即可:

$ sudo pip3 install Flask

进入python交互模式看下Flask的介绍和版本:

$ python3
 
>>> import flask
>>> print(flask.__doc__)
 
    flask
    ~~~~~
 
    A microframework based on Werkzeug.  It's extensively documented
    and follows best practice patterns.
 
    :copyright: © 2010 by the Pallets team.
    :license: BSD, see LICENSE for more details.
 
>>> print(flask.__version__)
1.0.2

三、从 Hello World 开始

本节主要内容:使用Flask写一个显示”Hello World!”的web程序,如何配置、调试Flask。

3.1 Hello World

按照以下命令建立Flask项目HelloWorld:

mkdir HelloWorld
mkdir HelloWorld/static
mkdir HelloWorld/templates
touch HelloWorld/server.py

statictemplates目录是默认配置,其中static用来存放静态资源,例如图片、jsCSS文件等。templates存放模板文件。
我们的网站逻辑基本在server.py文件中,当然,也可以给这个文件起其他的名字。

在server.py中加入以下内容:

from flask import Flask
 
app = Flask(__name__)
 
@app.route('/')
def hello_world():
    return 'Hello World!'
 
if __name__ == '__main__':
    app.run()

运行server.py:

$ python3 server.py 
 * Running on Http://127.0.0.1:5000/

打开浏览器访问http://127.0.0.1:5000/,浏览页面上将出现Hello World!
终端里会显示下面的信息:

127.0.0.1 - - [16/May/2014 10:29:08] "GET / HTTP/1.1" 200 -

变量app是一个Flask实例,通过下面的方式:

@app.route('/')
def hello_world():
    return 'Hello World!'

当客户端访问/时,将响应hello_world()函数返回的内容。注意,这不是返回Hello World!这么简单,Hello World!只是HTTP响应报文的实体部分,状态码等信息既可以由Flask自动处理,也可以通过编程来制定。

3.2 修改Flask的配置

app = Flask(__name__)

上面的代码中,python内置变量__name__的值是字符串__main__ 。Flask类将这个参数作为程序名称。当然这个是可以自定义的,比如app = Flask("my-app")

Flask默认使用static目录存放静态资源,templates目录存放模板,这是可以通过设置参数更改的:

app = Flask("my-app", static_folder="path2", template_folder="path3")

flask.render_template(template_name_or_list, **context)
Renders a template from the template folder with the given context.

  • flask.render_template_string(source, **context)
    Renders a template from the given template source string with the given context.

  • flask.get_template_attribute(template_name, attribute)
    Loads a Macro (or variable) a template exports. This can be used to invoke a macro from within Python code.

  • 这其中常用的就是前两个函数。

    这个实例中使用了模板继承、if判断、for循环。

    11.1 建立Flask项目

    按照以下命令建立Flask项目HelloWorld:

    mkdir HelloWorld
    mkdir HelloWorld/static
    mkdir HelloWorld/templates
    touch HelloWorld/server.py

    11.2 创建并编辑HelloWorld/templates/default.html

    内容如下:

    <html>
    <head>
        <title>
            {% if page_title %}
                {{ page_title }}
            {% endif %}
        </title>
    </head>
     
    <body>
        {% block body %}{% endblock %}
     
     
    ```
    可以看到,在``标签中使用了if判断,如果给模板传递了`page_title`变量,显示之,否则,不显示。
    ``标签中定义了一个名为`body`的block,用来被其他模板文件继承。
    ### 11.3 创建并编辑HelloWorld/templates/user_info.html
    内容如下:
    ```
    {% extends "default.html" %}
     
    {% block body %}
        {% for key in user_info %}
     
            {{ key }}: {{ user_info[key] }} 
     
     
        {% endfor %}
    {% endblock %}

    变量user_info应该是一个字典,for循环用来循环输出键值对。

    11.4 编辑HelloWorld/server.py

    内容如下:

    from flask import Flask, render_template
     
    app = Flask(__name__)
     
     
    @app.route('/')
    def hello_world():
        return 'hello world'
     
     
    @app.route('/user')
    def user():
        user_info = {
            'name': 'letian',
            'email': '123@aa.com',
            'age':0,
            'GitHub': 'https://github.com/letiantian'
        }
        return render_template('user_info.html', page_title='letian\'s info', user_info=user_info)
     
     
    if __name__ == '__main__':
        app.run(port=5000, debug=True)

    render_template()函数的第一个参数指定模板文件,后面的参数是要传递的数据。

    11.5 运行与测试

    运行HelloWorld/server.py:

    $ python3 HelloWorld/server.py

    在浏览器中访问http://127.0.0.1:5000/user

    查看网页源码

    <html>
    <head>
        <title>
                letian&&9;s info
        </title>
    </head>
    <body>
            name: letian <br/>
            email: 123@aa.com <br/>
            age: 0 <br/>
            github: https://github.com/letiantian <br/>
    </body>
    </html>

    十二、自定义404等错误的响应

    要处理HTTP错误,可以使用flask.abort函数。

    12.1 示例1:简单入门

    建立Flask项目

    按照以下命令建立Flask项目HelloWorld:

    mkdir HelloWorld
    mkdir HelloWorld/static
    mkdir HelloWorld/templates
    touch HelloWorld/server.py

    代码

    编辑HelloWorld/server.py:

    from flask import Flask, render_template_string, abort
     
    app = Flask(__name__)
     
     
    @app.route('/')
    def hello_world():
        return 'hello world'
     
     
    @app.route('/user')
    def user():
        abort(401)  # Unauthorized 未授权
        print('Unauthorized, 请先登录')
     
     
    if __name__ == '__main__':
        app.run(port=5000, debug=True)

    效果

    运行HelloWorld/server.py,浏览器访问http://127.0.0.1:5000/user

    要注意的是,HelloWorld/server.py中abort(401)后的print并没有执行。

    12.2 示例2:自定义错误页面

    代码

    服务器代码改为:

    from flask import Flask, render_template_string, abort
     
    app = Flask(__name__)
     
     
    @app.route('/')
    def hello_world():
        return 'hello world'
     
     
    @app.route('/user')
    def user():
        abort(401)  # Unauthorized
     
     
    @app.errorhandler(401)
    def page_unauthorized(error):
        return render_template_string('
     Unauthorized 
    {{ error_info }}', error_info=error), 401
     
     
    if __name__ == '__main__':
        app.run(port=5000, debug=True)

    page_unauthorized函数返回的是一个元组,401 代表HTTP 响应状态码。如果省略401,则响应状态码会变成默认的 200。

    效果

    运行HelloWorld/server.py,浏览器访问http://127.0.0.1:5000/user

    十三、用户会话

    session用来记录用户的登录状态,一般基于cookie实现。

    下面是一个简单的示例。

    13.1 建立Flask项目

    按照以下命令建立Flask项目HelloWorld:

    mkdir HelloWorld
    mkdir HelloWorld/static
    mkdir HelloWorld/templates
    touch HelloWorld/server.py

    13.2 编辑HelloWorld/server.py

    内容如下:

    from flask import Flask, render_template_string, \
        session, request, redirect, url_for
     
    app = Flask(__name__)
     
    app.secret_key = 'F12Zr47j\3yX R~X@H!jLwf/T'
     
     
    @app.route('/')
    def hello_world():
        return 'hello world'
     
     
    @app.route('/login')
    def login():
         return render_template_string(page)
    @app.route('/do_login', methods=['POST'])
    def do_login():
        name = request.fORM.get('user_name')
        session['user_name'] = name
        return 'success'
     
     
    @app.route('/show')
    def show():
        return session['user_name']
     
     
    @app.route('/loGout')
    def logout():
        session.pop('user_name', None)
        return redirect(url_for('login'))
     
     
    if __name__ == '__main__':
        app.run(port=5000, debug=True)

    13.3 代码的含义

    app.secret_key用于给session加密。

    /login中将向用户展示一个表单,要求输入一个名字,submit后将数据以post的方式传递给/do_login/do_login将名字存放在session中。

    如果用户成功登录,访问/show时会显示用户的名字。此时,打开firebug等调试工具,选择session面板,会看到有一个cookie的名称为session

    /logout用于登出,通过将session中的user_name字段pop即可。Flask中的session基于字典类型实现,调用pop方法时会返回pop的键对应的值;如果要pop的键并不存在,那么返回值是pop()的第二个参数。

    另外,使用redirect()重定向时,一定要在前面加上return

    13.4 效果

    进入http://127.0.0.1:5000/login,输入name,点击submit

    进入http://127.0.0.1:5000/show查看session中存储的name:

    Python如何使用Web框架Flask开发项目

    13.5 设置sessin的有效时间

    下面这段代码来自Is there an easy way to make sessions timeout in flask?:

    from datetime import timedelta
    from flask import session, app
     
    session.permanent = True
    app.permanent_session_lifetime = timedelta(minutes=5)

    这段代码将session的有效时间设置为5分钟。

    十四、使用Cookie

    Cookie是存储在客户端的记录访问者状态的数据。 常用的用于记录用户登录状态的session大多是基于cookie实现的。

    cookie可以借助flask.Response来实现。下面是一个示例。

    14.1 建立Flask项目

    按照以下命令建立Flask项目HelloWorld:

    mkdir HelloWorld
    mkdir HelloWorld/static
    mkdir HelloWorld/templates
    touch HelloWorld/server.py

    14.2 代码

    修改HelloWorld/server.py:

    from flask import Flask, request, Response, make_response
    import time
     
    app = Flask(__name__)
     
     
    @app.route('/')
    def hello_world():
        return 'hello world'
     
     
    @app.route('/add')
    def login():
        res = Response('add cookies')
        res.set_cookie(key='name', value='letian', expires=time.time()+6*60)
        return res
     
     
    @app.route('/show')
    def show():
        return request.cookies.__str__()
     
     
    @app.route('/del')
    def del_cookie():
        res = Response('delete cookies')
        res.set_cookie('name', '', expires=0)
        return res
     
     
    if __name__ == '__main__':
        app.run(port=5000, debug=True)

    由上可以看到,可以使用Response.set_cookie添加和删除cookie。expires参数用来设置cookie有效时间,它的值可以是datetime对象或者unix时间戳,笔者使用的是unix时间戳。

    res.set_cookie(key='name', value='letian', expires=time.time()+6*60)

    上面的expire参数的值表示cookie在从现在开始的6分钟内都是有效的。

    要删除cookie,将expire参数的值设为0即可:

    res.set_cookie('name', '', expires=0)

    set_cookie()函数的原型如下:

    set_cookie(key, value=&rsquo;&rsquo;, max_age=None, expires=None, path=&rsquo;/&lsquo;, domain=None, secure=None, httponly=False)

    Sets a cookie. The parameters are the same as in the cookie Morsel object in the Python standard library but it accepts unicode data, too.
    Parameters:

    key &ndash; the key (name) of the cookie to be set.
    value &ndash; the value of the cookie.
    max_age &ndash; should be a number of seconds, or None (default) if the cookie should last only as long as the client&rsquo;s browser session.

    expires &ndash; should be a datetime object or UNIX timestamp.

    domain &ndash; if you want to set a cross-domain cookie. For example, domain=”.example.com” will set a cookie that is readable by the domain www.example.com, foo.example.com etc. Otherwise, a cookie will only be readable by the domain that set it.

    path &ndash; limits the cookie to a given path, per default it will span the whole domain.

    14.3 运行与测试

    运行HelloWorld/server.py:

    $ python3 HelloWorld/server.py

    使用浏览器打开http://127.0.0.1:5000/add,浏览器界面会显示

    add cookies

    下面查看一下cookie,如果使用firefox浏览器,可以用firebug插件查看。打开firebug,选择Cookies选项,刷新页面,可以看到名为name的cookie,其值为letian

    在“网络”选项中,可以查看响应头中类似下面内容的设置cookie的HTTP「指令」:

    Set-Cookie: name=letian; Expires=Sun, 29-Jun-2014 05:16:27 GMT; Path=/

    在cookie有效期间,使用浏览器访问http://127.0.0.1:5000/show,可以看到:

    {'name': 'letian'}

    十五、闪存系统 flashing system

    Flask的闪存系统(flashing system)用于向用户提供反馈信息,这些反馈信息一般是对用户上一次操作的反馈。反馈信息是存储在服务器端的,当服务器向客户端返回反馈信息后,这些反馈信息会被服务器端删除。

    下面是一个示例。

    15.1 建立Flask项目

    按照以下命令建立Flask项目HelloWorld:

    mkdir HelloWorld
    mkdir HelloWorld/static
    mkdir HelloWorld/templates
    touch HelloWorld/server.py

    15.2 编写HelloWorld/server.py

    内容如下:

    from flask import Flask, flash, get_flashed_messages
    import time
     
    app = Flask(__name__)
    app.secret_key = 'some_secret'
     
     
    @app.route('/')
    def index():
        return 'hi'
     
     
    @app.route('/gen')
    def gen():
        info = 'access at '+ time.time().__str__()
        flash(info)
        return info
     
     
    @app.route('/show1')
    def show1():
        return get_flashed_messages().__str__()
     
     
    @app.route('/show2')
    def show2():
        return get_flashed_messages().__str__()
     
     
    if __name__ == "__main__":
        app.run(port=5000, debug=True)

    15.3 效果

    运行服务器:

    $ python3 HelloWorld/server.py

    打开浏览器,访问http://127.0.0.1:5000/gen,浏览器界面显示(注意,时间戳是动态生成的,每次都会不一样,除非并行访问):

    access at 1404020982.83

    查看浏览器的cookie,可以看到session,其对应的内容是:

    .eJyrVopPy0kszkgtVrKKrlZSKIFQSUpWSknhYVXJRm55UYG2tkq1OlDRyHC_rKgIvypPdzcDTxdXA1-XwHLfLEdTfxfPUn8XX6DKWCAEAJKBGq8.BpE6dg.F1VURZa7VqU9bvbC4XIBO9-3Y4Y

    再一次访问http://127.0.0.1:5000/gen,浏览器界面显示:

    access at 1404021130.32

    cookie中session发生了变化,新的内容是:

    .eJyrVopPy0kszkgtVrKKrlZSKIFQSUpWSknhYVXJRm55UYG2tkq1OlDRyHC_rKgIvypPdzcDTxdXA1-XwHLfLEdTfxfPUn8XX6DKWLBaMg1yrfCtciz1rfIEGxRbCwAhGjC5.BpE7Cg.Cb_B_k2otqczhknGnpNjQ5u4dqw

    然后使用浏览器访问http://127.0.0.1:5000/show1,浏览器界面显示:

    ['access at 1404020982.83', 'access at 1404021130.32']

    这个列表中的内容也就是上面的两次访问http://127.0.0.1:5000/gen得到的内容。此时,cookie中已经没有session了。

    如果使用浏览器访问http://127.0.0.1:5000/show1或者http://127.0.0.1:5000/show2,只会得到:

    []

    15.4 高级用法

    flash系统也支持对flash的内容进行分类。修改HelloWorld/server.py内容:

    from flask import Flask, flash, get_flashed_messages
    import time
     
    app = Flask(__name__)
    app.secret_key = 'some_secret'
     
     
    @app.route('/')
    def index():
        return 'hi'
     
     
    @app.route('/gen')
    def gen():
        info = 'access at '+ time.time().__str__()
        flash('show1 '+info, category='show1')
        flash('show2 '+info, category='show2')
        return info
     
     
    @app.route('/show1')
    def show1():
        return get_flashed_messages(category_filter='show1').__str__()
     
    @app.route('/show2')
    def show2():
        return get_flashed_messages(category_filter='show2').__str__()
     
     
    if __name__ == "__main__":
        app.run(port=5000, debug=True)

    某一时刻,浏览器访问http://127.0.0.1:5000/gen,浏览器界面显示:

    access at 1404022326.39

    不过,由上面的代码可以知道,此时生成了两个flash信息,但分类(category)不同。

    使用浏览器访问http://127.0.0.1:5000/show1,得到如下内容:

    ['1 access at 1404022326.39']

    而继续访问http://127.0.0.1:5000/show2,得到的内容为空:

    []

    15.5 在模板文件中获取flash的内容

    在Flask中,get_flashed_messages()默认已经集成到Jinja2模板引擎中,易用性很强。

    以上就是Python如何使用Web框架Flask开发项目的详细内容,更多请关注其它相关文章!

    相关文章