Flask Web 开发实战
The Flask Mega-Tutorial

数据库:数据库设计(需求,设计,运行,维护)-CSDN博客

同济——GitHub项目

wenshaofeng/bikeMs: 学习用react写共享单车后台管理系统 (github.com)

软件建模与分析–共享单车管理系统-CSDN博客

计算机毕业设计springboot校园共享单车系统的设计与实现0v1439[附源码]

实战开始

创建项目

第一步就遇到困难,完全不知道如何下手,
选择GitHub上公开的项目进行补充修改,操作系统采用Windows 11,数据库采用MySQL,后端框架采用Flask,编程语言是python

Flask框架学习

搭建Flask环境:

1
2
3
4
5
6
7
8
9
10
11
12
13
pip install flask
pip install pipenv

在项目目录下创建虚拟环境
pipenv install
激活虚拟环境
pipenv shell
在虚拟环境里安装Flask
pipenv install flask
更新Flask
pipenv update flask
查看项目对应的虚拟环境路径
pipenv --venv

启动开发服务器:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
在虚拟环境中运行(提前激活虚拟环境 pipenv shell)
flask run
主程序文件名应为app.py或者wsgi.py,否则需要设置环境变量FLASK_APP的模块名
$ export FLASK_APP=hello.py # linux
> set FLASK_APP=hello.py # windows

管理环境变量
pipenv install python-dotenv
创建.env文件(用来存放包含敏感信息的环境变量,例如账号密码)
创建.flaskenv文件(用来存放和FLASK相关的公开环境变量,例如FLASK_APP)

设置运行环境:
在.flaskenv文件中添加
FLASK_ENV=development # 开发环境development,默认为production(生产环境)


# 安装watchdog 监听文件变化,自动重启服务器
pipenv install watchdog --dev

项目配置:

1
2
在项目根目录下创建config.py文件

使用pipenv安装扩展Flask-WTF处理表单:
pipenv install flask-wtf

路由

Python Flask 简明教程(7)–路由使用方法详解

路由就是URL和Python函数的映射关系,说的再明白点,就是客户端请求哪个路径交给哪个函数处理的问题。
通过给函数添加装饰器@app.route,即可定义路由,装饰器的参数即为对应的URL。

URL介绍

也就是说装饰器的参数设置成什么就会匹配什么资源路径(Path to resource)
@app.route(‘/hello’)
访问http://127.0.0.1:5000/hello,由于该访问地址URL匹配'/hello',所以将被处理。

动态控制路由(重定向)
通过redirect()函数即可动态控制路由。
return redirect(url_for(‘login’))

URL参数
有时候,我们希望接受URL上附带的参数,此时可以通过在装饰器上添加格式的内容,来对应URL传递的参数

装饰器

Python 函数装饰器
python 装饰器详解

装饰器就是在一个函数里嵌套一个或者多个函数,在这些函数里使用了顶层函数的参数(不管是参数是值还是函数),然后构造出来一个装饰器,在调用时对其他值或者函数用装饰器,最终输出时参数的值被装载了装饰器的函数或值替换(赋值)。

python装饰器总结一句话:采用了闭包的思路(内外函数嵌套,内函数引用外函数作用域下的非全局变量,外函数返回内函数的引用),在不改变原函数代码的前提下为函数增添新的功能

@wraps(func) # 继承原函数,调用时不改变函数原含义

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
def a_new_decorator(a_func):

def wrapTheFunction():
print("I am doing some boring work before executing a_func()")

a_func()

print("I am doing some boring work after executing a_func()")

return wrapTheFunction

def a_function_requiring_decoration():
print("I am the function which needs some decoration to remove my foul smell")

a_function_requiring_decoration()
#outputs: "I am the function which needs some decoration to remove my foul smell"

a_function_requiring_decoration = a_new_decorator(a_function_requiring_decoration)
#now a_function_requiring_decoration is wrapped by wrapTheFunction()

a_function_requiring_decoration()
#outputs:I am doing some boring work before executing a_func()
# I am the function which needs some decoration to remove my foul smell
# I am doing some boring work after executing a_func()

print(a_function_requiring_decoration.name)

Output: wrapTheFunction
使用装饰器会导致调用函数的名称被覆盖成装饰器的内层函数,这里用functools.wraps装饰内层函数就可以解决这个问题

初始化

1
2
3
4
5
6
7
8
def __init__(self, host, user, password, db, charset):
self.host = host
self.user = user
self.password = password
self.db = db
self.charset = charset
self.conn = pymysql.connect(host = host, user = user, password = password, db = db, charset = charset) //连接MySQL数据库
self.cur = self.conn.cursor() //游标

WTF表单

字段 说明 对应的HTML表示
StringField 文本字段
TextAreaField 多行文本字段
PasswordField 密码文本字段
HiddenField 隐藏文本字段
DateField 文本字段,值为datetime.date格式
DateTimeField 文本字段,值为datetime.datetime格式
IntegerField 文本字段,值为整数
DecimalField 文本字段,值为decimal.Decimal
FloatField 文本字段,值为浮点数
BooleanField 复选框,值为True和False
RadioField 一组单选框
SelectField 下拉列表
SelectMultipleField 下拉列表,可选择多个值
FileField 文件上传字段
SubmitField 表单提交按钮
FormField 把表单作为字段嵌入另一个表单
FieldList 一组指定类型的字段

WTF表单验证

验证器 说明
DataRequired 确保字段中有数据
Email 验证电子邮件地址
EqualTo 比较两个字段的值;常用于要求输入两次密码进行确认的情况
InputRequired 确保字段中有数据
IPAddress 验证IPv4网络地址
Length 验证输入字符串的长度在数字范围内
NumberRange 验证输入的值在数字范围内
Optional 无输入值时跳过其他验证函数
Required 确保字段中有数据
Regexp 使用正则表达式验证输入值
URL 验证URL
AnyOf 确保输入值在可选值列表中
NoneOf 确保输入值不在可选值列表中

实例化字段类常用参数

参数 说明
label 标签
validators 验证器
render_kw 渲染控件的属性,一个字典,用来设置对应的HTML标签的属性
default 默认值
filters 过滤器
description 描述信息
widget 渲染控件

WTF表单安全

Flask-WTF内置了CSRF保护,可以抵御跨站请求伪造攻击。

CSRF

跨站请求伪造(CSRF)是一种冒充受信任用户,向服务器发送非预期请求的攻击方式。例如,这些非预期请求可能是通过在跳转链接后的 URL 中加入恶意参数来完成:

表单中包含一个隐藏字段csrf_token,用来存放CSRF令牌,这个令牌是一个加密字符串,Flask-WTF使用这个令牌验证请求中表单数据的真伪。
默认情况下,使用程序密钥来CSRF令牌进行签名:

1
app.secret_key = "secret string"

处理表单数据

  1. 解析请求,获取表单数据
  2. 对数据进行必要的转换,比如将勾选框的值转换成Python的布尔值
  3. 对数据进行验证,确保数据要求,同时验证CSRF令牌
  4. 如果验证未通过则需要生成错误信息,并在模板中渲染表单显示错误信息,让用户可以修正
  5. 如果通过验证,则将数据保存到数据库中,或者执行其他操作
提交表单
属性 默认值 说明
action 当前URL,即页面对应的URL 表单提交时发送请求的目标URL
method GET 表单提交时使用的HTTP方法
enctype application/x-www-form-urlencoded 请求的数据编码方式
autocomplete on 浏览器是否可以自动完成表单
验证表单数据

客户端验证:在浏览器中使用JavaScript验证表单数据,可以提高用户体验,但是不可靠,因为用户可以禁用JavaScript。
服务器端验证:在服务器端验证表单数据,可以确保数据符合要求,但是会增加服务器的负载。
使用POST方法提交的表单,其数据会被Flask解析为一个字典,可以通过request.form来访问这个字典。
使用GET方法提交的表单,其数据会被Flask解析为一个不可变的MultiDict,可以通过request.args来访问这个字典。

tools.py

1
2
3
4
5
6
7
8
def create_all(self):
with open('bike.sql', 'r', encoding = 'utf-8') as init_file:
text = init_file.read()
lines = text.split('----')
for line in lines:
self.cur.execute(line)
if 'insert' in line or 'update' in line or 'delete' in line:
self.conn.commit()

bike.sql
– 为了自动读取本文件并初始化, 需要在每条语句后加 —-
– 但注意最后一句不要加 —-

项目配置

为什么需要使用自己的配置?
假设你在做一个博客,有十个视图函数都定义了每页显示的文章数。当你写好以后,发现每页的文章太多,想把这个值改小一点,这时你要找到这十个视图函数,分别修改这个值,很蠢吧?使用配置你就使用一行控制所有的变量:
app.config['POST_PER_PAGE'] = 12

设置配置

  • 直接写出配置的值,像上面那样。
  • 对于不适合写在程序里的配置,比如密码等,需要把配置写入系统环境变量,然后使用os模块的getenv()方法获取,第二个参数作为默认值
1
2
3
4
5
6
import os

from flask import Flask

app = Flask(__name__)
app.config['MAIL_USERNAME'] = os.getenv('MAIL_USERNAME', 'me@greyli.com')

如果使用虚拟环境,设置环境变量时注意要激活虚拟环境,同时不要给变量值加引号。
set MAIL_USERNAME=me@greyli.com # 结果是'me@greyli.com'
set MAIL_USERNAME='me@greyli.com' # 结果是"'me@greyli.com'"
处理配置

  • 直接写入主脚本
  • 单独的配置文件
    • 通过Json文件,app.config.from_json
1
2
3
4
{
"FLASK_ENV":"json"
"SECRET_KEY":"some secret words"
}
  • 通过 python文件,app.config.from_object 或 app.config.from_pyfile
1
2
3
SECRET_KEY = 'some secret words'
DEBUG = True
ITEMS_PER_PAGE = 10

app.secret_key、cookie、session

解密Flask app.secret_key

会话技术、Cookies、Session详解
程序可以把数据存储在用户会话中,用户会话是-种私有存储,默认情况下,它会保存在客户端cookie中。Flask提供了session对象来操作用户会话。session 是基于cookie实现, 保存在服务端的键值对(形式为 {随机字符串:‘xxxxxx’}), 同时在浏览器中的cookie中也对应一相同的随机字符串,用来再次请求的时候验证

Flask中的session是存在浏览器中 默认key是session(加密的cookie),使用session时要设置一个密钥app. secret_ key

Flask API

flash函数 - 闪现信息

flask-flash函数
闪现信息就是 只展示一次的数据/参数.

应用:

比如进入首页只刷一次的广告.

render_template和redirect函数及其区别

Flask render_template和redirect的区别
render_template函数
render_template函数是Flask框架中的一个重要函数,其主要作用是将指定的模板文件渲染成HTML页面并返回给客户端。该函数通常用于将动态数据与静态的HTML模板结合,实现页面的动态展示。
redirect函数
redirect函数是Flask框架中的另一个重要函数,其主要作用是将用户重定向到指定的URL。当我们在处理某些请求时,希望将用户重定向到另一个URL时,可以使用redirect函数实现这个功能。
区别

  • render_template函数用于渲染模板,返回HTML页面;redirect函数用于重定向,将用户跳转到另一个URL;
  • render_template函数常用于页面展示,并且需要与路由函数配合使用;redirect函数常用于重定向到其他页面或执行其他操作;
  • render_template函数返回的是生成的HTML页面代码;redirect函数返回的是一个新的URL,用户的浏览器将会跳转到该URL。

Jinja2 模板继承

模板继承
Python web 框架 Flask 模板使用
Django 使用了“模板继承”的概念:这就是{% extends "base.html" %}所做的事。它意味着 “首先载入名为 ‘base’ 的模板中的内容到当前模板,然后再处理本模板中的其余内容。”总之,模板继承让你在模板间大大减少冗余内容:每一个模板只需要定义它独特的部分即可。

将模板转换为完整的HTML页面的操作称为渲染。 为了渲染模板,需要从Flask框架中导入一个名为render_template()的函数。 该函数需要传入模板文件名和模板参数的变量列表,并返回模板中所有占位符都用实际变量值替换后的字符串结果。

render_template()函数调用Flask框架原生依赖的Jinja2模板引擎。 Jinja2用render_template()函数传入的参数中的相应值替换{{...}}块。

模板也支持在{%...%}块内使用控制语句

1
2
3
4
5
6
7
# 条件语句
{% if title %}
{% else %}
{% endif %}
# 循环语句
{% for i in array %}
{% endfor %}

error

ConnectionRefusedError: [WinError 10061] 由于目标计算机积极拒绝,无法连接。
猜测原因:MySQL未连接成功
尝试解决方法:重新下载并配置环境
MySQL8.0的安装、配置、启动服务和登录及配置环境变量

下载并配置好后,错误代码发生变化,证明思路正确
New error:
pymysql.err.OperationalError: (1045, “Access denied for user ‘root‘@’localhost’ (using password: YES)”)

原因:数据库user:root的连接密钥错误
更换所有__init__的初始化数据库函数的参数
util = MySQLTools(‘localhost’, ‘root’, ‘Qq13239349089’, ‘sharebike’, ‘utf8’) //Qq13239349089是我的数据库密钥
New error:
AttributeError: ‘Flask’ object has no attribute ‘before_first_request’. Did you mean: ‘_got_first_request’?
原因:flask2.3.0已经弃用钩子函数’before_first_request’

solution:pip install Flask==2.2.5
用搜索引擎查找相关问题,答案比较少,有一篇说明是2.3.0版本删除了钩子函数,但没有对更新后如何修改进行说明的贴子,因此选择退回版本

项目跑成功了!

经过一番折腾,这该死的项目终于能跑起来了,之后就是看懂再增删改了,明天把文档写一写

要做的内容:
单车管理
骑行者管理
押金管理
骑行管理
其他功能:查询统计、用户权限管理、异常处理(单车故障、押金不足、骑行者黑名单等)等

从网页开始读代码

开发环境:

Windows系统
Pycharm 软件

前端框架 Bootstrap
后端框架 Flask

数据库 MySQL

<link href = "/static/bootstrap/dist/css/bootstrap.min.css" rel = "stylesheet">
采用了bootstrap框架,但版本较低,之后可以考虑更新版本

尝试增加功能:用户界面,点击右上角的图像可以转到

鼠标悬停页面头部用户图像出现下拉菜单的实现
点击头像选择图片更换头像
点击头像更换头像

修改内容-删去同济相关文字

抠图好tm麻烦

高德地图 查询地理经纬度

实现功能

1.自动登录 session与cookie
2.数据库加密 python cryptography

3.动态生成导航栏 JS改写

使用最小代价去更新,利用Web Components技术

4.解决一下网页打开慢的问题
5.并发量大的时候,数据库会崩溃,需要解决 测试
解决高并发的系统设计
网站性能测试指标及网站压力测试
6.重新设计页面 优秀的交互设计(比如说单车点击可借)
7.无障碍功能设计
8.小功能 (更换语言,更换主题,更换背景,更换字体)