from flask import Flask
app=Flask(__name__)
@app.route('/index')
def index():
return "你好Flask"
if __name__ == '__main__':
app.run(host="0.0.0.0", debug=True, port=8000)
host
指定运行的主机,127.0.0.1表示本机运行,0.0.0.0 表示可以通过网络访问
dubug
指定调试模式,错误是否在网页端显示
port
运行的服务器端口号
注意:出现”以一种访问权限不允许的方式做了一个访问套接字的尝试“错误,很有可能是端口号被占用
下载安装pymysql
下载安装 Flask-SQLAlchemy
在Flask程序中一般不直接使用pymysql直接写原生SQL语句去操作数据库,更多的是通过SQLAlchemy提供的ORM技术去操作数据库。Flask-SQLAlchemy是在Flask中操作关系型数据库的拓展,是以面向模型对象的形式操作数据库,避免传统通过SQL语句进行数据库操作的复杂度和安全性。
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
# 数据库配置信息
HOSTNAME = "127.0.0.1"
PORT = 3306
USERNAME = "root"
PASSWORD = "123456"
DATABASE = "flask"
app.config['SQLALCHEMY_DATABASE_URI'] = f"mysql+pymysql://{USERNAME}:{PASSWORD}@{HOSTNAME}:{PORT}/{DATABASE}?charset=utf8mb4"
db = SQLAlchemy(app)
class User(db.Model):
__tablename__ = "user"
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
username = db.Column(db.String(100), nullable=False)
password = db.Column(db.String(100), nullable=False)
#自动生成表
with app.app_context():
db.create_all()
class Article(db.Model):
__tablename__ = "article"
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
title = db.Column(db.String(200), nullable=False)
content = db.Column(db.String(100), nullable=False)
# 添加作者外键
author_id = db.Column(db.Integer, db.ForeignKey("user.id"))
# 添加关联对象属性,backref 会自动给User模型添加一个articles的属性
author = db.relationship("User", backref="articles")
给文章表创建一个外键author_id 对应user表中的id字段
添加一个author属性,对应文章的一个User,并反向在在User类中创建一个articles的属性,用于返回当前作者的所有的文章
@app.route('/useradd/')
def userAdd():
user=User(username = "李子豪", password = "234")
db.session.add(user)
db.session.commit()
result=Result(msg="添加成功!")
resDict=vars(result) #对象转化为字典
print(resDict)
return jsonify(resDict)
@app.route('/useradd2/')
def userAdd2():
user=User()
user.username="郑振华"
user.password="456"
db.session.add(user)
db.session.commit()
result=Result(msg="添加成功!")
resDict=vars(result) #对象转化为字典
print(resDict)
return jsonify(resDict)
user=User.query.all()
采用user=User.query.get(1) ,get 的参数是主键的值
@app.route('/getuser1/')
def getUser1():
user=User.query.get(31) #根据主键查找
if user is None:
res=Result(code="fail",msg="记录不存在")
return jsonify(vars(res))
else:
res=Result(msg="查找成功")
res.data.append(user.toDict())
return jsonify(vars(res))
user=User.query.first()
res=User.query.count()
采用User.query.filter_by(username=“张五”) 通过 filter_by 查询条件的方式进行查询,查询的结果可能有多个值。
注意:filter_by() 只能筛选条件等于,不支持 大于 (>)和小于 (<)和 and_、or_查询
@app.route('/getuser2/')
def getUser2():
userLst=User.query.filter_by(username="张五")
res = Result(msg="查找成功")
for user in userLst :
res.data.append(user.toDict())
if len(res.data)<=0 :
res2=Result(code="fail",msg="记录不存在")
return jsonify(vars(res2))
else:
return jsonify(vars(res))
模型类.query.fillter_by(字段名 =值)
等价于 select * from user where 字段名=值
模型类.query.fillter_by(字段名 =值).first()
等价于 select * from user where 字段名=值 limit 1
模型类.query.fillter(模型类.字段名.like('%z%')).all()
等价于 select * from user where 字段名 like '%z%'
模型类.query.fillter(模型类.字段名.in_(['a','b','c'])).all()
等价于 select * from user where 字段名 in ('a','b','c')
模型类.query.fillter(模型类.字段名.between(开始,结束)).all()
等价于 select * from user where 字段名 between 开始 and 结束
in_函数的使用
我们使用了in_函数来创建in子句查询条件。在Flask SQLAlchemy中,in_函数用于将列表或子查询包装成一个in子句查询条件。我们可以通过调用模型类的属性和方法以及SQLAlchemy提供的函数来构建复杂的查询条件。下面是一些常用的in_函数的使用示例:
使用模型类的属性:User.query.filter(User.name.in_([‘Alice’, ‘Bob’, ‘Charlie’])).all()
使用子查询:User.query.filter(User.id.in_(db.session.query(Order.user_id).filter(Order.status == ‘completed’))).all()
使用函数:User.query.filter(User.age.in_(db.session.query(func.avg(User.age)).group_by(User.department)))).all()
from sqlalchemy import or_, and_, not_
.query.fillter(or_(模型类.字段名.like('z%'),模型类.字段名.contains('a'))).all()
等价于 select * from user where 字段名 like 'z%' or 字段名 like '%a%'
.query.fillter(and_(模型类.字段名.like('z%'),模型类.字段名 < '2021-12-12 00:00:00')).all()
等价于 select * from user where 字段名 like 'z%' and 字段名 < '2021-12-12 00:00:00'
query.order_by (模型类.字段名.desc()).all()
等价于 select * from user order by 字段名 desc
模型类.query.fillter(模型类.字段名==值).order_by (模型类.字段名.desc()).all()
等价于 select * from user where 字段名=值 order by 字段名 desc
查询记录,如果用query.filter_by 查询可以用first()返回查询的第一条记录
user=User.query.filter_by(username="王五").first() #返回查询的第一条记录
user.password="88888"
db.session.commit()
修改记录的对应值
调用session的commit方法,更新缓存,保存到数据库
@app.route('/userdelete/')
def userDelete():
user = User.query.filter_by(username="张三").first() # 返回查询的第一条记录
db.session.delete(user)
db.session.commit()
return "成功"
安装Authlib
包
调用以下代码设置token信息
# 生成token
header = {'alg': 'HS256'} #签名算法
key = current_app.config['SECRET_KEY'] #用于签名的密钥
data={"id":user.id,"username":user.username} # token中存放的用户数据
token=jwt.encode(header=header, payload=data, key=key).decode('utf-8') #生成token
@bp.route("/getApp",methods=["POST"])
def getApp():
getToken=request.headers.get("token")
result = Result()
if getToken is None :
result.state=401
result.msg="没有权限"
else:
userId=Dbtools.getUserId(getToken)
user=User.query.get(userId)
result.data=user.toDict()
return jsonify(vars(result))
通过app.json.ensure_ascii = False
可以实现中文uncode编码问题。
app = Flask(__name__)
app.json.ensure_ascii = False
注意:在Flask 2.3.2版本下 app.config['JSON_AS_ASCII'] = False
解决中文编码方式无效
Content-Type: application/json 自动为json格式,不用进行设置
基本用法如下,resDict为字典格式
return jsonify(resDict)
类对象转化为字典,result为一个类对象,resDict是一个字典
resDict=vars(result) #对象转化为字典
#定义一个结果类,用于返回结果
class Result :
def __init__(self,state = 200, code = "success" ,msg = ""):
self.state=state
self.code=code
self.msg=msg
self.data=dict() #创建空字典
state
状态码,(200:成功,400:失败,401:认证失败,无权限,502:拒绝)code
响应代码(success:成功,error:失败)msg
响应消息data
响应数据创建config.py文件用于存储app的相关配置
# 数据库配置信息
HOSTNAME = "127.0.0.1"
PORT = 3306
USERNAME = "root"
PASSWORD = "123456"
DATABASE = "flask"
DB_URI = "mysql+pymysql://{}:{}@{}:{}/{}?charset=utf8mb4".format(USERNAME,PASSWORD,HOSTNAME,PORT,DATABASE)
SQLALCHEMY_DATABASE_URI = DB_URI
在mian.py 中导入config.py ,并绑定配置文件
app.config.from_object(config) # 导入数据库配置信息
创建exts.py
把相关数据库操作的扩展包,放在该文件下防止重复导入,循环引用
在main.py中导入
from Exts import db , Result
在main.py 中绑定app
db.init_app(app)
创建python 包,名称可以随意,用于存放路由的蓝图
创建蓝图相关代码,核心代码bp=Blueprint("user",__name__,url_prefix="/user")
url_prefix 用于指定路由的前缀
from flask import Blueprint
from Exts import db,Result
bp=Blueprint("user",__name__,url_prefix="/user")
@bp.route("/add")
def userAdd():
pass
导入并注册蓝图
from Route.User import bp as user_bp
……
app.register_blueprint(user_bp) # 注册蓝图
from flask import Flask
from Exts import db
import config
from Route.User import bp as user_bp
from models import *
from flask_cors import CORS
app = Flask(__name__)
app.json.ensure_ascii = False
CORS(app, resources=r'/*') #可以跨域访问
app.config.from_object(config) # 导入数据库配置信息
db.init_app(app) #取代 db = SQLAlchemy(app)
with app.app_context():
db.create_all()
app.register_blueprint(user_bp)
if __name__ == '__main__':
app.run(host="0.0.0.0", debug=False, port=8000)
当客户端向服务器端请求ajax服务时,如果客户端和服务器端域名不一致,就会出现跨域问题,ajax报错如下:
No 'Access-Control-Allow-Origin' header is present on the requested
安装flask_cors
app初始化的时候就加载配置
from flask import Flask
from flask_cors import CORS
app = Flask(__name__)
# r'/*' 是通配符,让本服务器所有的 URL 都允许跨域请求
CORS(app, resources=r'/*')
if __name__ == "__main__":
app.run()