Flask从入门到入土

所谓人生苦短, 我用 Python. 经常戏称别的语言 Python 化, 不就是说明了 Python 作为现代语言的优越性. 当然, 不吹不贬地说, 其实关键在于项目需求, 所以用什么其实并不重要.

在 Python Web 开发这块, Django 和 Flask 平分天下, 而 Flask 框架的优点就在于它"轻量", "微", 简直就是 vscode 的翻版, 靠社区 extension 高效驱动.

当然, Flask 的使用不局限于 Web 应用的开发, 甚至说, 作为后端提供接口才是发挥它功用的最好做法. 这正是本文要完成的事情!

先把框架搭好. 其它的之后再说.

后端: 交互数据库

前后端: 简单来说就是前端负责页面和交互, 后端负责提供数据以及实现与数据库的交互

后端干的事情一点也不酷

工欲善其事, 必先利其器

当然, 你要安装 Flask

配好 Python 开发环境. 我这里用的是WSL, 推荐大家尽可能的去熟悉Linux的开发环境.

白嫖学生优惠 JetBrains 全家桶: 推荐 PyCharm, 专属 IDE, 你值得拥有. 说得好, 我用 VSCode

推荐在虚拟环境 venv 中开发.

建议在 .bashrc 里写 alias, 方便配置:

1
2
alias pylab='python3 -m venv .venv'
alias activate='source .venv/bin/activate'

Git 是你的基本功

平时 Github 解决一切. 但也记得上手 Gitlab, 因为企业一般用的它. Gitee 是什么真不熟

学习 Git 分支

  • git clone: 克隆项目副本 2023年了不要还在问为什么SSH connection refused
  • git checkout [-b] [feature-name]: 切换分支 (-b 顺带创建分支)
  • git add .: 把当前路径下的文件放到暂存区
  • git commit -m "Message": 提交暂存的更改 不要问在IDE里怎么退出VIM :wq
  • git pull [--rebase] origin main: 避免落后主分支, 顺带处理冲突
  • git push origin main: 推送到主分支

以上操作 IDE 其实都有GUI. 不需要你手敲.

文档编写/测试工具

这一部分因人而异. 这里只给出我使用的工具:

Show Doc: 文档编写工具(项目组用的)

Postman: 接口测试工具 其实命令行工具 curl 对于后端测试简单的接口来说就够了

数据库系统

我们使用关系型数据库系统: MySQL

实验室的老师贴心地为你在外网搭建了一个 MySQL 的数据连接. 没有被MySQL安装折磨过的人生是不完整的

我的平台: WSL 安装参考这篇微软的文章

解决第三方插件连接 Access Denied: 原因是 MySQL 把 Windows 下的程序视作远程 MYSQL 请求, 如果没有远程权限就会出错.

解决方案:

sudo mysql 进入 mysql:

1
2
3
4
5
6
USE mysql;
-- 创建一个账号, 不带密码
-- 注: IDENTIFIED BY password with GRANT 语句在 MySQL ver 5.7.6 不再适用
CREATE USER 'besthope'@'localhost' IDENTIFIED BY '';
GRANT ALL PRIVILEGES ON *.* TO 'besthope'@'localhost';
FLUSH PRIVILEGES;

我使用的 VScode 插件: My SQL(个人认为最方便的一个) 或者Pycharm里连接MySQL

先别急着 coding, 你还有文档没写

产品原型——先解构

对产品原型的解构. 大致的实现需求. 好了, 这就是你的 TODO-LIST.

看起来比较复杂的项目, 分模块分时期去实现, 一个页面一个页面慢慢来.

RESTful API

简单介绍 REST 架构和 Web 基础

RESTful 架构是个什么东西? Representational State Transfer是 REST 的全称, "表现层状态发生转移".

REST 对信息的核心抽象就是 资源(Resources), 通常以 URI(统一资源定位符) 的形式表现. 这里的资源可以是文本, 图片, 或者任何能被命名的信息. 换句话说, 如果某一信息能被超链接导航到, 那它就符合资源的定义. 要访问某一"资源", 访问它的 URI 即可. URI 就是这个"资源"独一无二的标识符!

不过要注意的是, "资源"是对信息的抽象: 它代表的是一组相关的实体, 而非一个单独的实体. 具体的实体会发生变化, 但"资源"表示实体的结构和行为是不变的.

"资源"具体表现的形式, 就称作它的"表现层"(Representation).

例如, 文本可以用 txt 格式表现, 也可以用 JSON, xml 格式, 甚至二进制格式表现; 图片可以用 jpg 格式表现, 也可以用 png 格式表现.

访问一个网站, 就代表了客户端和服务器的一个互动过程. 在这个过程中, 必然涉及数据和状态的改变. 互联网通信协议HTTP 协议, 是一个无状态协议. 所有的状态都保存在服务器端, 如果客户端想要操作服务器, 必须通过某种途径, 使得服务器端发生"状态转移"(State Transfer). 而这种状态转移是建立在表现层之上的. 所以, 你现在就能明白 REST 到底指的是个啥.

至于客户端用到的手段, 只能是HTTP 的请求方法. 下面这五种方法对应的 CRUD(增删改查) 操作:

请求方法 效果
GET 读取(Read)
POST 新建(Create)
PUT 更新(Update)
PATCH 更新(Update),通常是部分更新
DELETE 删除(Delete)

根据HTTP协议, 请求方法(Request)由客户端提出, 由服务器决定是否执行或拒绝. 例如, 你发起了一个 GET 请求, 想获取 /clients 下的资源. 但这个文件获取需要有权限, 服务器就可以有如下的执行方式:

  • 404 Not found: 这个状态码表示文件不存在. 当然是服务器装的.
  • 403 Forbidden: 这个文件拒绝访问.
  • 405 Method Not Allowed: 然后用 Allow 头告诉你可以用 HEAD 方法获取文件的元信息.

RESTful 的设计细节

主要内容:

  • URI 设计:
    • 任何请求都是动宾结构. 例如 GET /images /create-order
    • 使用集合资源: 为了避免单数出现的歧义. images/2 image/2
    • 避免多级 URI: 尽量避免三级以上. /authors/12?categories=2(字符串查询) /authors/12/categories/2
    • 字符串查询: Filtering, Sorting, and Pagination GET: /articles/?published=true&page=2&page_size=20
  • 状态码设计:
  • 服务器回应:
    • 不要返回纯文本: HTTP 头的 Content-Type 属性要设为 application/json, 接受 JSON 结构化数据
    • 考虑 HATEOAS 将关联资源联系起来(提供超链接).

具体参考官方或者他人总结的教程.(见参考资料)

和前端配合

交流很重要.

确定哪些业务逻辑在放前端实现, 哪些业务逻辑放在后端实现.

看看 API 设计是否合理. 俩人得出共识就可以各干各的了.

我还没学过数据库

推荐介绍MySQL基础的一本书: MySQL应知应会

入门了解基础语法即可. 要用到的时候check cheatsheet 就好.

学有余力了再去学习DBMS的底层原理. 理解底层实现, 就和学习算法优化一样. 实际上, 这才是计算机系学生应当去学习的东西! CMU15-445 等你完成

创表: 你是个设计师, 老弟

CREATE TABLE: 一切的开始

创建表至少要包含名字, 还有一个列. 最好为表设置主键(不会重复的列).

1
2
3
4
5
6
7
8
-- 创建表: 一个简单的示例
CREATE TABLE customers
(
cust_id int NOT NULL AUTO_INCREMENT,
cust_name char(50) NOT NULL,
cust_city char(50) NULL,
PRIMARY KEY (cust_id)
) ENGINE=InnoDB;

不需要你手写 SQL 语句(当然你乐意也可以). 在插件里创建表之后就可以在GUI里设计表(ALTER)了.

can can need: 开源的 MySQL 数据库表设计

可以参考 SQL Style Guide.

一些比较重要的原则:

  • 驼峰命名不适合扫读.
  • 面向对象编程的原则(OOP)不该应用到 SQL 或数据库结构上.
  • 保证名字独一无二且不是保留字.
  • 尽量避免连接两个表的名字作为关系表的名字. cars_mechanics 不如用 services(别名的时候要注意)
  • 列名总是使用单数形式.
  • SQL关键字用大写, 数据库字段应当都是小写. 命名风格统一些. video_URL video_url
  • 等...

怎么实现关联表? 例如, 课程底下有视频, 怎么把视频表和课程表发生关联? 在设计表的时候就要考虑这一点. 实际上这并不复杂:

1
2
3
SELECT course_title, video_title
FROM videos, courses
WHERE videos.course_id = courses.id

也就是说, 我们在视频表里添加一个 course_id 的列, 作为外键, 它对应的是 courses 表下的主键 id. 这样 videos.course_id = courses.id 作为查询语句就可以将两个表进行关联了.

Query: 我只会增删改查

MySQL 的增删改查语句总结

学会 insert, update, delete, select

前三个 GUI 解决一切. 又快又好. 真要写 SQL 语句, 其实学起来也很快. 剩下一个查询语句是你尤其需要关注的. 简单来说, 你要掌握这些:

  • 通配符 和 REGEXG
  • 聚集函数例如 COUNT()
  • 分组数据 GROUP BYHAVING
  • 子查询(subquery)
  • 多表联合查询 例如 LEFT OUTER JOIN
  • ...

对于复杂的业务逻辑, 掌握上面的基本操作是一种必须. 同时, 追求性能则必然要求SQL语句的优化. 对于后端接口来说, GET 方法反而是最多的. 可以说, 真正要用SQL去写的需求其实只有查询(?)

怎么高效地从一个大型的数据库中提取数据, 这是一个很关键的问题! 学问很深, 待你慢慢研究.

好了, 现在开始进入 Flask

网上有很多优秀的 Flask 项目值得学习: Awesome Flask

迅速启动项目

Flask 比其它框架(例如 Spring Boot)好的一点在于它很干净.

1
2
3
4
5
6
7
8
9
10
11
12
13
from flask import Flask

app = Flask(__name__)


@app.route('/')
def hello_world(): # put application's code here
return 'Hello World!'


if __name__ == '__main__':
app.run()

配置文件

config.py 配置环境

工厂函数和蓝图

啊这, 真的要再写一遍 Model 吗

sqlacodegen

血的教训: 配好你的环境

只返回JSON而已, 很简单

jsonify

最喜欢的一集: 写测试

unitest

其实不用太在意写测试

参考资料

  1. SQL Style Guide
  2. Flask Web 开发: 基于 Python 的 Web 应用开发实践: 第 2 版. ISBN 978-7-115-48945-6
  3. Roy Thomas Fielding 在他 2000 年的博士论文提出的 REST 原则
  4. REST API 的官方教程
  5. 阮一峰, RESTful API 最佳实践.
  6. 微软出品的API教程
  7. Web API Checklist
  8. Error using GRANT with IDENTIFIED by password in MySQL: 讨论了为什么 MySQL 5.7.6 之后为什么不再适用 GRANT IDENTIFIED BY.
  9. Flask 官方中文文档.