python中的web框架Flask,连接mysql实现增删改查

408 阅读6分钟

创建一个python项目

image.png

image.png

创建完成之后项目目录应该是长下面这个样子

image.png

接下来我们要做的就是安装 Flask 和 mysql ,点击侧边栏的 Terminal,运行如下命令

    pip install flask 
    pip install flask-sqlalchemy
    pip install PyMySQL

image.png

安装完毕之后在项目的根目录新建app.py文件,先来一些简单的路由(接口)调用吧

from flask import Flask, render_template, request, redirect, jsonify, abort


# 传⼊__name__初始化⼀个Flask实例,默认写法
app = Flask(__name__)

# app.route装饰器映射URL和执⾏的函数。这个设置将根URL映射到了hello_world函数上,这个就相当于html中的主页面
@app.route('/')
def hello_world():
    return 'Hello World!'

@app.route('/test')
def test():
    return 'test'

@app.route('/page')
def page():
    return render_template('index.html') # 返回了一个html页面

# 重定向到百度
@app.route('/reshow')
def reshow():
    # 重定向到百度
    return redirect('https://www.baidu.com')




@app.route('/func1')
def func1():
    #  返回一个字典
    data = {'name':'fly'}
    return data

@app.route('/func3')
def func3():
    data = {'name':'fly'}
    return jsonify(data) #把别的类型转为json类型


# 获取表单数据
@app.route('/show', methods=['GET', 'POST'])
def show():
    if request.method == 'GET':
        return render_template('index.html')
    if request.method == 'POST':
        name = request.form.get('name')
        password = request.form.get('password')
        if name == 'fly' and password == '123':
            return f'账号是:{name}   密码是:{password}'
        else:
            abort(404)
            return None


# 异常处理
@app.errorhandler(404)
def handle_404(e):
    return '404错误<br>%s'%e


if __name__ == '__main__':
# 运⾏本项⽬,host=0.0.0.0可以让其他电脑也能访问到该⽹站,port指定访问的端⼝。默认的host是127.0.0.1,port为5000
    app.run()

在项目根目录下面建 templates 文件夹,并且在该文件夹下面新建index.html文件,用于此次测试

注意文件路径一定要正确,Flask 默认会在 templates 文件夹中查找模板文件。如果 index.html 文件未正确放置在 templates 文件夹中,会导致 render_template 无法找到文件

   <!DOCTYPE html>
   <html lang="en">
   <head>
       <meta charset="UTF-8">
       <title>Python</title>
   </head>
   <body>
       <h2>登录</h2>
       <form action="/show" method="POST">
           账号:
           <br>
           <input type="text" name="name">  <!-- name 属性与 show 方法中的 request.form.get('name') 一致 -->
           <br><br>
           密码:
           <br>
           <input type="text" name="password">  <!-- name 属性与 show 方法中的 request.form.get('password') 一致 -->
           <br><br>
           <input type="submit" name="submit" value="提交">
       </form>
   </body>
   </html>
   

关于 @app.route解释

这个注解就相当于是java当中的方法注解,在括号里面去定义方法名称,就相当于是给一个人起了一个名字,方便你更好的找到该方法进行调用 可以在页面或者浏览器的地址栏输入几个get方法的路径就可以看到代码中的一些东西会渲染在页面上,并且也可以渲染一个html

经过上面路由的测试,接下来进入主题,连接mysql实现增删改查,还是在app里面进行操作

链接mysql,且定义实体类(表中对应字段)

app = Flask(__name__)       #实例化Flask类
ctx = app.app_context()     #当一个请求被处理时,Flask会创建一个上下文,并把该上下文绑定到当前线程上。
ctx.push()                  #启动上下文
# 配置mysql链接信息
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql+pymysql://root:123456@localhost:3306/old_port'
db = SQLAlchemy(app) # 初始话数据库对象,并且与app进行绑定


class User(db.Model):
    __tablename__ = 'old_port_user' # 定义对哪一个表进行操作,设置表名,接下来是定义表中的一些字段
    id = db.Column(db.Integer, primary_key=True)
    old_port_username = db.Column(db.String(255), unique=True)
    old_port_password = db.Column(db.String(255), unique=True)
    create_by = db.Column(db.String(255))
    create_time = db.Column(db.DateTime, default=datetime.now)
    is_delete = db.Column(db.Boolean, default=False)

关于实体类字段关键字的种类及其作用

关键字作用示例
primary_key=True表示该字段是表的主键,值必须是唯一的,且不能为 Noneid = db.Column(db.Integer, primary_key=True)
nullable=False表示该字段不能为 None(即不能为空)old_port_username = db.Column(db.String(255), nullable=False)
default=默认值表示如果插入数据时未提供该字段的值,则使用默认值is_delete = db.Column(db.Boolean, default=False)
index=True表示为该字段创建索引,以提高查询性能old_port_username = db.Column(db.String(255), index=True)
autoincrement=True表示该字段的值自动递增,通常用于主键字段id = db.Column(db.Integer, primary_key=True, autoincrement=True)
onupdate=默认值表示在更新记录时,如果未提供该字段的值,则使用默认值update_time = db.Column(db.DateTime, onupdate=datetime.now)
server_default=默认值表示在数据库层面设置默认值,而不是在应用层面create_time = db.Column(db.DateTime, server_default=db.func.now())
comment='字段描述'为字段添加注释,描述字段的用途old_port_username = db.Column(db.String(255), comment='用户名')

准备工作完毕开始增删改查操作

@app.route('/insert_user',  methods=['POST'])
def insert_user():
    username = request.form.get('username')
    password = request.form.get('password')
    is_delete = False
    user = User(old_port_username=username, old_port_password=password, is_delete=is_delete)
    db.session.add(user)
    db.session.commit()

删(逻辑删除)

@app.route('/delete_user', methods=['GET'])
def delete_user():
    id = request.args.get('id')
    user = User.query.get(id)
    if user:
        user.is_delete = True
        db.session.commit()
        # 删除后回显被删除的用户信息
        return query_user(username=user.old_port_username)
    else:
        return jsonify({'error': '用户不存在'}), 404

@app.route('/update_user', methods=['POST'])
def update_user():
    id = request.form.get('id')
    username = request.form.get('username')
    password = request.form.get('password')
    user = User.query.get(id)
    if user:
        if username:
            user.old_port_username = username
        if password:
            user.old_port_password = password
        db.session.commit()
        return query_user(username)
    else:
        return '用户不存在', 404

@app.route('/query_user', methods=['GET'])
def query_user(username=None):
    if username is None:
        username = request.args.get('username')

    if username:
        users = User.query.filter_by(old_port_username=username).all()
    else:
        users = User.query.all()
    # 将 User 对象列表转换为字典列表
    users_dict = [user_to_dict(user) for user in users]
    return jsonify(users_dict)

关于查询接口解析

def query_user(username=None) 为什么要添加 username=None
因为查询用户的方法我还在删除用户里面取调用了的,但是那是内部方法调用,是不通过url的,所以需要定义接口参数
既然接口有username参数为什么还要在方法体里面,通过request请求里面去取username值
因为查询的话一般是根据用户名查询和查询全部用户,两个需求用一个接口去实现的,所以说需要添加一个usernam参数在这,这个接口是暴漏给前端取访问的,所以参数是拼接在url上的
所以其实是两种调用方式的区别,针对不同的调用方式,从不同的地方取取值,这四种方法都可以通过postman进行方法调用测试,达到会数据库的数据进行crud操作

附上数据库

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
-- Table structure for old_port_user
-- ----------------------------
DROP TABLE IF EXISTS `old_port_user`;
CREATE TABLE `old_port_user`  (
  `id` int NOT NULL AUTO_INCREMENT COMMENT '用户表',
  `old_port_username` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '用户名',
  `old_port_password` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '密码',
  `create_by` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '创建人',
  `modified_by` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '修改人',
  `create_time` datetime NULL DEFAULT NULL COMMENT '创建时间',
  `modified_time` datetime NULL DEFAULT NULL COMMENT '修改时间',
  `is_delete` tinyint NULL DEFAULT NULL COMMENT '是否删除',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 13 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;

SET FOREIGN_KEY_CHECKS = 1;