狗书无敌,天下第一(初识flask)

  为什么选择使用flask?

  和其他框架相比, Flask 之所以能脱颖而出,原因在于它让开发者做主,使其能对程序具有全面的创意控制。

  在 Flask 中,你可以自主选择程序的组件,如果找不到合适的,还可以自己开发。
  Flask 提供了一个强健的核心, 其中包含每个 Web 程序都需要的基本功能,而其他功能则交给行业系统中的众多第三方扩展。
  一句话概括就是flask不是一个高度定制化的web框架,你可以做到随心所欲,使用任何可能的扩展来完成你的项目。

  狗书的代码已上传GitHub:Companion code to my O‘Reilly book "Flask Web Development

  Flask 有两个主要依赖:路由、调试和 Web 服务器网关接口(Web Server Gateway Interface,WSGI)子系统由 Werkzeug(http://werkzeug.pocoo.org/)提供;模板系统由 Jinja2(http://jinja.pocoo.org/)提供。 Werkzeug 和 Jinjia2 都是由 Flask 的核心开发者开发而成。

  Flask 并不原生支持数据库访问、 Web 表单验证和用户认证等高级功能。这些功能以及其他大多数 Web 程序中需要的核心服务都以扩展的形式实现, 然后再与核心包集成。 
  安装

pip install flask

  初始化

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

from flask import Flask
app = Flask(__name__)

  也就是说,此时web框架接收的请求都会通过flask实例化的对象进行处理。

  这里的初始化方式是最简单的初始化方式,后面会使用到更为复杂的初始化方式。

  路由和视图函数

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

  在 Flask 程序中定义路由的最简便方式,是使用程序实例提供的 app.route 修饰器,把修饰的函数注册为路由。

@app.route(‘/‘)
def index():
    return ‘<h1>Hello World!</h1>‘

  这个函数的返回值称为响应,是客户端接收到的内容。如果客户端是 Web 浏览器, 响应就是显示给用户查看的文档(一般就是html页面)。

  程序实例用 run 方法启动 Flask 集成的开发 Web 服务器:

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

  有一些选项参数可被 app.run() 函数接受用于设置 Web 服务器的操作模式。在开发过程中启用调试模式会带来一些便利, 比如说激活调试器和重载程序。要想启用调试模式, 我们可以把 debug 参数设为 True。

  第一个程序:

from flask import Flask
app = Flask(__name__)

@app.route(‘/‘)
def index():
    return ‘<h1>Hello World!</h1>‘

@app.route(‘/user/<name>‘)
def user(name):
    return ‘<h1>Hello, {}!</h1>‘.format(name)
if __name__ == ‘__main__‘:
    app.run()

  为了避免大量可有可无的参数把视图函数弄得一团糟, Flask 使用上下文临时把某些对象变为全局可访问。有了上下文,就可以写出下面的视图函数:

from flask import request
@app.route(‘/‘)
def index():
    user_agent = request.headers.get(‘User-Agent‘)
    return ‘<p>Your browser is %s</p>‘ % user_agent

  这里我们把request当作全局变量使用,实际生产中每个线程都处理不同的请求,那么他们的request必然是不同的。Falsk 使用上下文让特定的变量在一个线程中全局可访问,与此同时却不会干扰其他线程。

  flask上下文全局变量

  没激活程序上下文之前就调用 current_app.name 会导致错误,但推送完上下文之后就可以调用了。 注意,在程序实例上调用 app.app_context() 可获得一个程序上下文。

from hello import app
from flask import current_app
app_ctx = app.app_context()
app_ctx.push()
current_app.name
‘hello‘

  URL 映射是 URL 和视图函数之间的对应关系。Flask 使用 app.route 修饰器或者非修饰器形式的 pp.add_url_rule() 生成映射。

app.url_map
Map([<Rule ‘/‘ (GET, HEAD, OPTIONS) -> index>,
 <Rule ‘/static/<filename>‘ (GET, HEAD, OPTIONS) -> static>,
 <Rule ‘/user/<name>‘ (GET, HEAD, OPTIONS) -> user>])

  / 和 /user/<name> 路由在程序中使用 app.route 修饰器定义。 /static/<filename> 路由是Flask 添加的特殊路由,用于访问静态文件。

  请求钩子

  Flask 支持以下 4 种钩子。

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

  注:在请求钩子函数和视图函数之间共享数据一般使用上下文全局变量 g。例如, before_request 处理程序可以从数据库中加载已登录用户,并将其保存到 g.user 中。随后调用视
图函数时,视图函数再使用 g.user 获取用户。

  响应

  flask的响应包括模板(本质是字符串)和状态码。

@app.route(‘/‘)
def index():
    return ‘<h1>Bad Request</h1>‘, 400

  如果不想返回由 1 个、 2 个或 3 个值组成的元组, Flask 视图函数还可以返回 Response 对象。 make_response() 函数可接受 1 个、 2 个或 3 个参数(和视图函数的返回值一样),并
返回一个 Response 对象。

from flask import make_response
@app.route(‘/‘)
def index():
    response = make_response(‘<h1>This document carries a cookie!</h1>‘)
    response.set_cookie(‘answer‘, ‘42‘)#创建对象,给对象加cookie
    return response

  flask重定向

from flask import redirect
@app.route(‘/‘)
def index():
    return redirect(‘http://www.example.com‘)

  abort生成响应404,abort 不会把控制权交还给调用它的函数,而是抛出异常把控制权交给 Web 服务器。

from flask import abort
@app.route(‘/user/<id>‘)
def get_user(id):
    user = load_user(id)
    if not user:
        abort(404)
    return ‘<h1>Hello, %s</h1>‘ % user.name

  使用Flask-Script支持命令行选项

  Flask 的开发 Web 服务器支持很多启动设置选项,但只能在脚本中作为参数传给 app.run()函数。这种方式并不十分方便,传递设置选项的理想方式是使用命令行参数。

  Flask-Script 是一个 Flask 扩展,为 Flask 程序添加了一个命令行解析器。 Flask-Script 自带了一组常用选项,而且还支持自定义命令。

pip install flask-script
from flask.ext.script import Manager
manager = Manager(app)

if __name__ == ‘__main__‘:
manager.run()

  专为 Flask 开发的扩展都暴漏在 flask.ext 命名空间下。 Flask-Script 输出了一个名为Manager 的类,可从 flask.ext.script 中引入。

  这个扩展的初始化方法也适用于其他很多扩展: 把程序实例作为参数传给构造函数,初始化主类的实例。 创建的对象可以在各个扩展中使用。在这里,服务器由 manager.run() 启
动,启动后就能解析命令行了。

from flask import Flask
from flask_script import Manager

app = Flask(__name__)

manager = Manager(app)

@app.route(‘/‘)
def index():
    return ‘<h1>Hello World!</h1>‘

@app.route(‘/user/<name>‘)
def user(name):
    return ‘<h1>Hello, %s!</h1>‘ % name

if __name__ == ‘__main__‘:
    manager.run()

  Jinja2模板引擎

  Jinja2模板引擎是flask默认的模板引擎。

   Flask 提供的 render_template 函数把 Jinja2 模板引擎集成到了程序中 。使用方式与django的render基本一致。

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

<p>A value from a dictionary: {{ mydict[‘key‘] }}.</p>
<p>A value from a list: {{ mylist[3] }}.</p>
<p>A value from a list, with a variable index: {{ mylist[myintvar] }}.</p>
<p>A value from an object‘s method: {{ myobj.somemethod() }}.</p>

  jinja2很大程度上和django的模板语言很类似,包括过滤器的使用,判断,循环,模板继承等。

  来说点特别的,jinja2支持宏(类似于函数,使用也和函数很像)。

  定义及使用宏:

{% macro render_comment(comment) %}
    <li>{{ comment }}</li>
{% endmacro %}
<ul>
    {% for comment in comments %}
        {{ render_comment(comment) }}
    {% endfor %}
</ul>

  重复使用宏需要将其保存在单独的文件中,然后在需要使用的模板中导入:

{% import ‘macros.html‘ as macros %}
<ul>
    {% for comment in comments %}
        {{ macros.render_comment(comment) }}
    {% endfor %}
</ul>

  要想在flask程序中集成 Bootstrap, 显然要对模板做所有必要的改动。不过,更简单的方法是使用一个名为 Flask-Bootstrap 的 Flask 扩展(这也是我喜欢flask的原因之一吧,扩展性强,插件还很多),简化集成的过程。

pip install flask-bootstrap

  初始化 Flask-Bootstrap

from flask.ext.bootstrap import Bootstrap
bootstrap = Bootstrap(app)

  初始化 Flask-Bootstrap 之后,就可以在程序中使用一个包含所有 Bootstrap 文件的基模板。

{% extends "bootstrap/base.html" %}
{% block title %}Flasky{% endblock %}

{% extends "bootstrap/base.html" %}

{% block title %}Flasky{% endblock %}

{% block navbar %}
<div class="navbar navbar-inverse" role="navigation">
    <div class="container">
        <div class="navbar-header">
            <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
                <span class="sr-only">Toggle navigation</span>
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
            </button>
            <a class="navbar-brand" href="/">Flasky</a>
        </div>
        <div class="navbar-collapse collapse">
            <ul class="nav navbar-nav">
                <li><a href="/">Home</a></li>
            </ul>
        </div>
    </div>
</div>
{% endblock %}

{% block content %}
<div class="container">
    <div class="page-header">
        <h1>Hello, {{ name }}!</h1>
    </div>
</div>
{% endblock %}

  自定制错误页面

@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

   url_for() 函数最简单的用法是以视图函数名(或者 app.add_url_route() 定义路由时使用的端点名)作为参数, 返回对应的 URL。例如,在当前版本的 hello.py 程序中调用 url_for(‘index‘) 得到的结果是 /。调用 url_for(‘index‘, _external=True) 返回的则是绝对地址,在这个示例中是 http://localhost:5000/。
  使用 url_for() 生成动态地址时,将动态部分作为关键字参数传入。例如, url_for(‘user‘, name=‘john‘, _external=True) 的返回结果是 http://localhost:5000/user/john。

  如果 Web 程序的用户来自世界各地,那么处理日期和时间可不是一个简单的任务。
  有一个使用 JavaScript 开发的优秀客户端开源代码库,名为 moment.js(http://momentjs.com/),它可以在浏览器中渲染日期和时间。 Flask-Moment 是一个 Flask 程序扩展,能把moment.js 集成到 Jinja2 模板中。

pip install flask-moment

  此模块依赖于moment.js 和jquery.js

from datetime import datetime
@app.route(‘/‘)
def index():
    return render_template(‘index.html‘,current_time=datetime.utcnow())

  渲染当前时间:

{% block scripts %}
{{ super() }}
{{ moment.include_moment() }}
{% endblock %}
<p>The local date and time is {{ moment(current_time).format(‘LLL‘) }}.</p>
<p>That was {{ moment(current_time).fromNow(refresh=True) }}</p>

  flask表单处理

pip install flask-wtf

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

app = Flask(__name__)
app.config[‘SECRET_KEY‘] = ‘hard to guess string‘

  定义表单类

from flask.ext.wtf import Form
from wtforms import StringField, SubmitField
from wtforms.validators import Required
class NameForm(Form):
    name = StringField(‘What is your name?‘, validators=[Required()])
    submit = SubmitField(‘Submit‘)

  这点flask-wtf要比django的form强大,类似于model form的功能。

  使用 Flask-Bootstrap方式渲染

{% import "bootstrap/wtf.html" as wtf %}
{{ wtf.quick_form(form) }}

  wtf.quick_form() 函数的参数为 Flask-WTF 表单对象,使用 Bootstrap 的默认样式渲染传入的表单。

  用户提交表单后, 服务器收到一个包含数据的 POST 请求。 validate_on_submit() 会调用name 字段上附属的 Required() 验证函数。如果名字不为空,就能通过验证, validate_on_submit() 返回 True。现在,用户输入的名字可通过字段的 data 属性获取。
  Flask-SQLAlchemy 是一个 Flask 扩展,简化了在 Flask 程序中使用 SQLAlchemy 的操作。SQLAlchemy 是一个很强大的关系型数据库框架, 支持多种数据库后台。 SQLAlchemy 提供了高层 ORM,也提供了使用数据库原生 SQL 的低层功能。

pip install flask-sqlalchemy

  配置数据库

from flask.ext.sqlalchemy import SQLAlchemy
basedir = os.path.abspath(os.path.dirname(__file__))
app = Flask(__name__)
app.config[‘SQLALCHEMY_DATABASE_URI‘] =‘sqlite:///‘ + os.path.join(basedir, ‘data.sqlite‘)
app.config[‘SQLALCHEMY_COMMIT_ON_TEARDOWN‘] = True
db = SQLAlchemy(app)

   db 对象是 SQLAlchemy 类的实例,表示程序使用的数据库,同时还获得了 Flask-SQLAlchemy提供的所有功能。

  定义数据库模型

class Role(db.Model):
    __tablename__ = ‘roles‘
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(64), unique=True)
    def __repr__(self):
        return ‘<Role %r>‘ % self.name

  创建数据库

(venv) $ python hello.py shell
>>> from hello import db
>>> db.create_all()

  删除数据库

db.drop_all()

  增加行数据

>>> from hello import Role, User
>>> admin_role = Role(name=‘Admin‘)
>>> mod_role = Role(name=‘Moderator‘)
>>> user_role = Role(name=‘User‘)
>>> user_john = User(username=‘john‘, role=admin_role)
>>> user_susan = User(username=‘susan‘, role=user_role)
>>> user_david = User(username=‘david‘, role=user_role)

  此时,我们的对象还只是自己意淫出来的,并没有往数据库中提交,我们需要通过数据库会话管理对数据库做改动 。

  第一步,将要提交对象加入会话中:

>>> db.session.add(admin_role)
>>> db.session.add(mod_role)
>>> db.session.add(user_role)
>>> db.session.add(user_john)
>>> db.session.add(user_susan)
>>> db.session.add(user_david)

  或者:

db.session.add_all([admin_role, mod_role, user_role,user_john, user_susan, user_david])

  为了把对象写入数据库,我们要调用 commit() 方法提交会话:

db.session.commit()

  此时,我们的对象已经真正的存在数据库中,可以查询到了。

  数据库会话能保证数据库的一致性。提交操作使用原子方式把会话中的对象全部写入数据库。如果在写入会话的过程中发生了错误, 整个会话都会失效。

  修改数据行

>>> admin_role.name = ‘Administrator‘
>>> db.session.add(admin_role)
>>> db.session.commit()

  删除数据库

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

  查询行数据

  Flask-SQLAlchemy 为每个模型类都提供了 query 对象。最基本的模型查询是取回对应表中的所有记录:

>>> Role.query.all()
[<Role u‘Administrator‘>, <Role u‘User‘>]
>>> User.query.all()
[<User u‘john‘>, <User u‘susan‘>, <User u‘david‘>]

  过滤查询

>>> User.query.filter_by(role=user_role).all()
[<User u‘susan‘>, <User u‘david‘>]

  如果你想看他在底层到底执行的sql语句是什么。

>>> str(User.query.filter_by(role=user_role))
‘SELECT users.id AS users_id, users.username AS users_username,
users.role_id AS users_role_id FROM users WHERE :param_1 = users.role_id‘

  为了避免一直重复导入,我们可以做些配置,让 Flask-Script 的 shell 命令自动导入特定的对象。

from flask.ext.script import Shell
def make_shell_context():
    return dict(app=app, db=db, User=User, Role=Role)
manager.add_command("shell", Shell(make_context=make_shell_context))

  使用Flask-Migrate实现数据库迁移

  配置 Flask-Migrate

from flask.ext.migrate import Migrate, MigrateCommand
migrate = Migrate(app, db)
manager.add_command(‘db‘, MigrateCommand)

  在维护数据库迁移之前,要使用 init 子命令创建迁移仓库:

python hello.py db init

  upgrade() 函数把迁移中的改动应用到数据库中, downgrade() 函数则将改动删除。

原文地址:https://www.cnblogs.com/Jeffding/p/8313263.html

时间: 2024-10-05 03:34:36

狗书无敌,天下第一(初识flask)的相关文章

Python Flask 狗书电子版pdf

Python Flask 狗书电子版pdf 链接:https://pan.baidu.com/s/197PUp5jXLnDRnkpr3VfHJw 提取码:87xx 内容简介 · · · · · · 本书不仅适合初级Web开发人员学习阅读,更是Python程序员用来学习高级Web开发技术的优秀参考书. 学习Flask应用的基本结构,编写示例应用: 使用必备的组件,包括模板.数据库.Web表单和电子邮件支持: 使用包和模块构建可伸缩的大型应用: 实现用户认证.角色和个人资料: 在博客网站中重用模板.

python之初识Flask

一.初识Flask Python三大主流Web框架对比 1.三大框架的特点 Django 主要特点是大而全,集成了很多组件,例如: Models Admin Form 等等, 不管你用得到用不到,反正它全都有,属于全能型框架 Tornado 主要特点是原生异步非阻塞,在IO密集型应用和多任务处理上占据绝对性的优势,属于专注型框架 Flask 主要特点小而轻,原生组件几乎为0, 三方提供的组件请参考Django 非常全面,属于短小精悍型框架 2.三大框架的优缺点 Django 通常用于大型Web应

初识 flask

flask是一个轻量级框架,它默认依赖2个外部库:Jinja2 模板. WSGI工具集--Werkzeug. flask的使用特点是基本所有的工具使用都依赖于导入的形式去扩展,flask只保留了web开发的核心功能. 通常:我们学习一个web框架只需要学会 如何使用路由.如何使用视图函数与模板语法.如何导入数据库 就可以跑通一个web项目 安装Flask:pip install flask 安装Flash:pip install flask 1|0一.Werkzeug简介 代码示例: from

Python进阶(四十九)-初识Flask Blueprint

Python进阶(四十九)-初识Flask Blueprint 前言   在进行Python Web开发时选择Flask框架.项目模块划分阶段,使用Blueprint(这里暂且称之为“蓝本”).Blueprint通过把实现不同功能的module分开,从而把一个大的application分割成各自实现不同功能的module.在一个Blueprint中可以调用另一个blueprint的view function, 但要加相应的blueprint名.   Blueprint还有其他好处,其本质上来说就

初识Flask

首先在学习flask的前提,我是使用了很久的django和tornado,现在在写总结也是本着工作后方便使用flask 少点东西,对flask的介绍和优点总结 1.安装 pip install flask 或者python setup.py install 2.测试是否安装成功 import flask 看有没有报错 安装成功

python常用框架之一 Flask (1) 初识Flask

---恢复内容开始--- Flask Flask诞生于2010年,是Armin ronacher(人名)用 Python 语言基于 Werkzeug 工具箱编写的轻量级Web开发框架. Flask 本身相当于一个内核,其他几乎所有的功能都要用到扩展(邮件扩展Flask-Mail,用户认证Flask-Login,数据库Flask-SQLAlchemy),都需要用第三方的扩展来实现. 比如可以用 Flask 扩展加入ORM.窗体验证工具,文件上传.身份验证等.Flask 没有默认使用的数据库,你可以

Flask初识,第九篇,Flask中的蓝图

蓝图,听起来就是一个很宏伟的东西 在Flask中的蓝图 blueprint 也是非常宏伟的 它的作用就是将 功能 与 主服务 分开怎么理解呢? 比如说,你有一个客户管理系统,最开始的时候,只有一个查看客户列表的功能,后来你又加入了一个添加客户的功能(add_user)模块, 然后又加入了一个删除客户的功能(del_user)模块,然后又加入了一个修改客户的功能(up_user)模块,在这个系统中,就可以将 查看客户,修改客户,添加客户,删除客户的四个功能做成蓝图加入到客户管理系统中,本篇最后会做

重新捡起flask(四)

中间一个礼拜没有看过flask了,今天重新捡起来,一切又开始陌生了.强迫自己看下去,也算是有了收获. 以前大概到这里就开始没有怎么实际写过代码了,其实看书,和实际写代码还真是差的很远. 刚看了没多久,由于自己现在是自己手敲,所以走了一些弯路,但这些弯路其实对于成长来说,还真是很有用的. 这里我举个刚刚遇到的例子. 不知道为什么博客园好像上传图片的服务出问题了 命令行还不能复制,蛋疼的很,我还是口述吧. from flask import Flask, render_template from f

从0开始使用python flask编写博客网站(1)

在学完flask教程时候,总是会遇到难以自己写项目的问题.在第一次看狗书的时候,作者从单文件马上就到了多文件的项目组织,当时也是仔细看,慢慢打代码才渐渐的明白了flask的项目组织方法,当明白了又感觉很简单..使用中多思考多打代码才能日有所得,愿你我共同成长. 1. 编写项目骨架 一个博客网站需要什么呢? 首页展示博客文章的概览 单页文章展示 后台管理 管理员登录 增加文章 修改文章 删除文章 错误页面 这就是一个最简单的博客需要的东西了.那么我分为三个路由负责三个大的功能.再加上静态文件,模板