美文网首页
Flask Web开发笔记

Flask Web开发笔记

作者: WooiiiWooiii | 来源:发表于2016-12-21 10:13 被阅读0次

    Flask笔记

    2.1初始化

    Web 服务器使用一种名为 Web 服务器网关接口
    (Web Server Gateway Interface,WSGI)的协议,把接收自客户端的所有请求都转交给这个对象处理。程序实例是 Flask 类的对象

    2.2 路由和视图函数

    程序实例需要知道对每个 URL 请求运行哪些代码,所以保存了一个URL到
    Python 函数的映射关系。处理 URL 和函数之间关系的程序称为路由。

    在 Python 代码中嵌入响应字符串会导致代码难以维护

    2.3启动服务器

    name=='main' 是 Python 的惯常用法,在这里确保直接执行这个脚本时才启动开发Web 服务器。如果这个脚本由其他脚本引入,程序假定父级脚本会启动不同的服务器,因此不会执行 app.run()。

    服务器启动后,会进入轮询,等待并处理请求。轮询会一直运行,直到程序停止,比如按Ctrl-C 键。

    2.5请求-响应循环
    2.5.1 程序和请求上下文

    Flask 使用上下文临时把某些对象
    变为全局可访问。

    变量名 上下文 说明
    current_app 程序上下文 当前激活程序的程序实例
    g 程序上下文 处理请求时用作临时存储的对象。每次请求都会重设这个变量
    request 请求上下文 请求对象,封装了客户端发出的
    session 请求上下文 用户会话,用于存储请求之间需要“记住”的值的词典
    2.5.2 请求调度

    程序收到客户端发来的请求时,要找到处理该请求的视图函数。为了完成这个任务,Flask
    会在程序的 URL 映射中查找请求的 URL。URL 映射是 URL 和视图函数之间的对应关系。
    Flask 使用 app.route 修饰器或者非修饰器形式的 app.add_url_rule() 生成映射。

    2.5.3 请求钩子

    有时在处理请求之前或之后执行代码会很有用

    • before_first_request:注册一个函数,在处理第一个请求之前运行。
    • before_request:注册一个函数,在每次请求之前运行。
    • after_request:注册一个函数,如果没有未处理的异常抛出,在每次请求之后运行。
    • teardown_request:注册一个函数,即使有未处理的异常抛出,也在每次请求之后运行。
    2.5.4 响应

    Flask 调用视图函数后,会将其返回值作为响应的内容。大多数情况下,响应就是一个简
    单的字符串,作为 HTML 页面回送客户端。

    但 HTTP 协议需要的不仅是作为请求响应的字符串。HTTP 响应中一个很重要的部分是状
    态码,Flask 默认设为 200,这个代码表明请求已经被成功处理。

    3.1 Jinja2模板引擎

    3.1.1 渲染模板

    Flask 提供的 render_template 函数把 Jinja2 模板引擎集成到了程序中。render_template 函
    数的第一个参数是模板的文件名

    3.1.2 变量

    在模板中使用的 {{ name }} 结构表示一个变量,它是一种特殊的占位符,告诉模
    板引擎这个位置的值从渲染模板时使用的数据中获取。

    Jinja2 能识别所有类型的变量,甚至是一些复杂的类型,例如列表、字典和对象。在模板

    可以使用过滤器修改变量,过滤器名添加在变量名之后,中间使用竖线分隔。例如,下述
    模板以首字母大写形式显示变量 name 的值:
    Hello, {{ name|capitalize }}

    3.1.3 控制结构

    下面这个例子展示了如何在模板中使用条件控制语句:

    {% if user %}
     Hello, {{ user }}!
    {% else %}
     Hello, Stranger!
    {% endif %}
    

    另一种常见需求是在模板中渲染一组元素。下例展示了如何使用 for 循环实现这一需求:

     <ul>
     {% for comment in comments %}
     <li>{{ comment }}</li>
     {% endfor %}
     </ul>
    
    

    Jinja2 还支持宏。宏类似于 Python 代码中的函数。

    需要在多处重复使用的模板代码片段可以写入单独的文件,再包含在所有模板中,以避免
    重复:

    {% include 'common.html' %}
    
    3.2 使用Flask-Bootstrap集成Twitter Bootstrap

    Bootstrap(http://getbootstrap.com/)是 Twitter 开发的一个开源框架,它提供的用户界面组
    件可用于创建整洁且具有吸引力的网页,而且这些网页还能兼容所有现代 Web 浏览器。

    3.3 自定义错误页面

    像常规路由一样,Flask 允许程序使用基于模板的自定义错误页面。最常见的错误代码有
    两个:404,客户端请求未知页面或路由时显示;500,有未处理的异常时显示。为这两个
    错误代码指定自定义处理程序的方式如示例 3-6 所示。

    @app.errorhandler(404)
    def page_not_found(e):
     return render_template('404.html'), 404
    @app.errorhandler(500)
    def internal_server_error(e):
     return render_template('500.html'), 500
    

    3.4 链接
    在模板中直接编写简单路由的 URL 链接不难,但对于包含可变部分的动态路由,在模板
    中构建正确的 URL 就很困难。而且,直接编写 URL 会对代码中定义的路由产生不必要的
    依赖关系。如果重新定义路由,模板中的链接可能会失效。

    为了避免这些问题,Flask 提供了 url_for() 辅助函数,它可以使用程序 URL 映射中保存的信息生成 URL。

    3.5 静态文件

    默认设置下,Flask 在程序根目录中名为 static 的子目录中寻找静态文件。如果需要,可在static 文件夹中使用子文件夹存放文件。

    3.6 使用Flask-Moment本地化日期和时间

    服务器需要统一时间单位,这和用户所在的地理位置无关,所以一般使用协调世界时
    (Coordinated Universal Time,UTC).不过用户看到 UTC 格式的时间会感到困惑,他们更希望看到当地时间,而且采用当地惯用的格式。

    一个优雅的解决方案是,把时间单位发送给 Web 浏览器,转换成当地时间,然后渲染。

    4.1 跨站请求伪造保护

    默认情况下,Flask-WTF 能保护所有表单免受跨站请求伪造(Cross-Site Request Forgery,
    CSRF)的攻击。恶意网站把请求发送到被攻击者已登录的其他网站时就会引发 CSRF 攻击。

    为了实现 CSRF 保护,Flask-WTF 需要程序设置一个密钥。Flask-WTF 使用这个密钥生成
    加密令牌,再用令牌验证请求中表单数据的真伪。设置密钥的方法如示例 4-1 所示。

    4.2 表单类

    使用 Flask-WTF 时,每个 Web 表单都由一个继承自 Form 的类表示。这

    4.3 把表单渲染成HTML

    表单字段是可调用的,在模板中调用后会渲染成 HTML。假设视图函数把一个 NameForm 实例通过参数 form 传入模板,在模板中可以生成一个简单的表单,如下所示:

    <form method="POST">
     {{ form.hidden_tag() }}
     {{ form.name.label }} {{ form.name() }}
     {{ form.submit() }}
    </form>
    
    
    4.4 在视图函数中处理表单

    不仅要渲染表单,还要接收表单中的数据

    4.5 重定向和用户会话

    程序可以把数据存储在用户会话中,在请求之间“记住”数据。用户会话是一种私有存储,存在于每个连接到服务器的客户端中

    4.6 Flash消息

    请求完成后,有时需要让用户知道状态发生了变化。这里可以使用确认消息、警告或者错误提醒。

    仅调用 flash() 函数并不能把消息显示出来,程序使用的模板要渲染这些消息。最好在基模板中渲染Flash 消息,因为这样所有页面都能使用这些消息。Flask 把get_flashed_messages() 函数开放给模板,用来获取并渲染消息

    5.1 SQL数据库

    关系型数据库把数据存储在表中,表模拟程序中不同的实体。

    表的列数是固定的,行数是可变的。列定义表所表示的实体的数据属性。

    表中有个特殊的列,称为主键,其值为表中各行的唯一标识符。表中还可以有称为外键的列,引用同一个表或不同表中某行的主键。行之间的这种联系称为关系,这是关系型数据库模型的基础。

    5.2 NoSQL数据库

    所有不遵循上节所述的关系模型的数据库统称为 NoSQL 数据库。

    使用 NoSQL 数据库当然也有好处。数据重复可以提升查询速度。列出用户及其角色的操作很简单,因为无需联结

    5.3 使用SQL还是NoSQL

    SQL 数据库擅于用高效且紧凑的形式存储结构化数据。这种数据库需要花费大量精力保证数据的一致性。NoSQL 数据库放宽了对这种一致性的要求,从而获得性能上的优势。

    5.4 Python数据库框架

    Flask 并不限制你使
    用何种类型的数据库包,因此可以根据自己的喜好选择使用 MySQL、Postgres、SQLite、Redis、MongoDB 或者 CouchDB。

    1. 易用性
    2. 性能
    3. 可移植性
    5.5 使用Flask-SQLAlchemy管理数据库

    Flask-SQLAlchemy 是一个 Flask 扩展,简化了在 Flask 程序中使用 SQLAlchemy 的操作。

    5.6 定义模型

    模型这个术语表示程序使用的持久化实体。

    5.7 关系

    关系型数据库使用关系把不同表中的行联系起来。

    5.8 数据库操作
    5.8.1 创建表

    方法是使用 db.create_all()

    5.8.2 插入行

    db.session.add(admin_role)

    5.8.3 修改行

    db.session.add(admin_role)
    db.session.commit()

    5.8.4 删除行

    db.session.delete(mod_role)
    db.session.commit()

    5.8.5 查询行

    Flask-SQLAlchemy 为每个模型类都提供了 query 对象

    5.9 在视图函数中操作数据库
    5.10 集成Python shell

    每次启动 shell 会话都要导入数据库实例和模型,这真是份枯燥的工作。为了避免一直重复导入,我们可以做些配置,让 Flask-Script 的 shell 命令自动导入特定的对象。

    5.11 使用Flask-Migrate实现数据库迁移
    7.1 项目结构

    多文件 Flask 程序的基本结构

    |-flasky
     |-app/
        |-templates/
        |-static/
        |-main/
            |-__init__.py
            |-errors.py
            |-forms.py
            |-views.py
        |-__init__.py
        |-email.py
        |-models.py
     |-migrations/
     |-tests/
        |-__init__.py
        |-test*.py
     |-venv/
     |-requirements.txt
     |-config.py
     |-manage.py
    

    这种结构有 4 个顶级文件夹:

    • Flask 程序一般都保存在名为 app 的包中;
    • 和之前一样,migrations 文件夹包含数据库迁移脚本;
    • 单元测试编写在 tests 包中;
    • 和之前一样,venv 文件夹包含 Python 虚拟环境

    同时还创建了一些新文件:

    • requirements.txt 列出了所有依赖包,便于在其他电脑中重新生成相同的虚拟环境;
    • requirements.txt 列出了所有依赖包,便于在其他电脑中重新生成相同的虚拟环境;
    • manage.py 用于启动程序以及其他的程序任务。
    7.2 配置选项

    程序经常需要设定多个配置。这方面最好的例子就是开发、测试和生产环境要使用不同的数据库,这样才不会彼此影响。

    7.3 程序包

    程序包用来保存程序的所有代码、模板和静态文件。我们可以把这个包直接称为app

    7.3.1 使用程序工厂函数

    在单个文件中开发程序很方便,但却有个很大的缺点,因为程序在全局作用域中创建,所以无法动态修改配置。运行脚本时,程序实例已经创建,再修改配置为时已晚。这一点对单元测试尤其重要,因为有时为了提高测试覆盖度,必须在不同的配置环境中运行程序。

    这个问题的解决方法是延迟创建程序实例,把创建过程移到可显式调用的工厂函数中。这种方法不仅可以给脚本留出配置程序的时间,还能够创建多个程序实例,这些实例有时在测试中非常有用。

    7.3.2 在蓝本中实现程序功能

    蓝本和程序类似,也可以定义路由。不同的
    是,在蓝本中定义的路由处于休眠状态,直到蓝本注册到程序上后,路由才真正成为程序的一部分。使用位于全局作用域中的蓝本时,定义路由的方法几乎和单脚本程序一样。

    7.4 启动脚本

    顶级文件夹中的 manage.py 文件用于启动程序。

    7.5 需求文件

    程序中必须包含一个 requirements.txt 文件,用于记录所有依赖包及其精确的版本号。如果要在另一台电脑上重新生成虚拟环境,这个文件的重要性就体现出来了,例如部署程序时使用的电脑。pip 可以使用如下命令自动生成这个文件:

    (venv) $ pip freeze >requirements.txt
    
    7.6 单元测试
    7.7 创建数据库
    8.1 Flask的认证扩展
    8.2 密码安全性

    相关文章

      网友评论

          本文标题:Flask Web开发笔记

          本文链接:https://www.haomeiwen.com/subject/tjqqvttx.html