当前位置: 首页 > news >正文

Web 框架 Flask 快速入门(三)数据库-MySQL

课程地址:Python Web 框架 Flask 快速入门

文章目录

  • 数据库
    • 1、数据库的安装与配置
    • 2、数据库的简单使用——增删改
      • 1. 定义数据模型
      • 2. 增删改
    • 3、 关系引用——表的关联
    • 4、查询——通过SQLAlchemy扩展
    • 5、其他
      • 1. 数据模型的实现(疑惑)
    • 6、Bug记录
      • 1. 1045,"Access denied for user 'root'@'localhost' "(using password: YES)
      • 2. RuntimeError: Working outside of application context


数据库

1、数据库的安装与配置

这节用到flask的两个扩展,使用pip安装扩展就行

pip install flask-sqlalchemy
pip install flask-mysqldb

然而,扩展只是基于数据库的一个抽象工具,就是说它只能让你的数据库更好用,但它本身并不是数据库。在使用这两个扩展之前,你还需要安装一个MySQL数据库。

参考:MySQL数据库安装教程(详细)

按教程中的压缩包方法,反正我安装成功了,如果遇到问题,可以翻翻评论区试试。

完成安装和配置后,数据库本地服务的启动流程:

# 1.登录数据库:打开cmd,输入下面命令。成功后会显示一段Welcome的话
C:\Users\ThinkPad>mysql -u用户名 -p 密码
# 2. 创建数据库:如果创建过,可跳过
mysql> create database flask_sql_demo charset=utf8;
# 3. 启动已创建的数据库
mysql> use flask_sql_demo;

MySQL较常见的一些命令:

# 1. 显示所有表单名
mysql> show tables;
# 2. 查看一个表单的字段结构(数据字典)
mysql> desc 表单名;
# 3. 查看一个表单的内容
mysql> select * from 表单名;
# 4. 关闭数据库 --> 显示Bye
mysql> quit
# 5. 显示所有数据库
mysql> show databases;
# 6. 删除数据表
mysql> drop table 数据表名;
# 7. 删除数据库
mysql> drop database 数据库名;

2、数据库的简单使用——增删改

1. 定义数据模型

增删改的操作对象是数据表,所谓“定义数据模型”,应该就是定义表的结构。

运行代码前,并不需要在终端登录数据库,脚本中本身就会登录。在终端登录数据库可以方便查看数据库的状态。

from flask import Flask
from flask_sqlalchemy import SQLAlchemyapp = Flask(__name__)# 配置数据库的地址,url结构为'mysql://用户名:密码@IP地址/数据库名'
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://root:写你的密码@127.0.0.1/flask_sql_demo2'# 数据库实例
db = SQLAlchemy(app)'''
两张表
角色(管理员,普通用户)
用户(角色id)
'''# 数据库的模型,需要继承db.Model
class Role(db.Model):# 定义表名__tablename__ = 'roles'# 定义字段 --> db.Column表示是一个字段id = db.Column(db.Integer, primary_key=True)name = db.Column(db.String(16), unique=True)class User(db.Model):__tablename__ = 'users'id = db.Column(db.Integer, primary_key=True)name = db.Column(db.String(16), unique=True)email = db.Column(db.String(32),unique=True)password = db.Column(db.String(32))# db.ForeignKey('roles.id'),表示是外键,表名.idrole_id = db.Column(db.Integer, db.ForeignKey('roles.id'))# -- main --
ctx = app.app_context()
ctx.push()
db.drop_all() # 删除旧表
db.create_all() # 创建新表
ctx.pop()

然后可以在终端使用mysql命令查看创建的表单

mysql> show tables;
+---------------------------+
| Tables_in_flask_sql_demo2 |
+---------------------------+
| roles                     |
| users                     |
+---------------------------+
2 rows in set (0.00 sec)

2. 增删改

Flask-SQLAlchemy的数据是有会话(Session)管理的,在增、删或修改操作后,都需要有一个提交步骤,然后变更才会在数据库中生效。

1、增加数据

ro1 = Role(name='admin')
db.session.add(ro1)
db.session.commit()

也可以批量添加提交数据

ro1 = Role(name='admin')
ro2 = Role(name='user')
db.session.add_all([ro1, ro2])
db.session.commit()

2、修改数据

ro1.name = 'other'
db.session.commit()

3、删除数据

db.session.delete(ro1)
db.session.commit()

3、 关系引用——表的关联

我们之前定义的表users中,有一个外键role_id,是关联到表roles的。如果要从表users中要得到一个用户的角色的名字,就只能先得到角色的id,然后拿着这个id再到roles表中去找角色的名字,就是说需要经过两次查询。

“关系引用”的

  • 作用:上述过程我只需要一次查询就可以得到用户的角色名。

  • 条件:需要是“一对多”的关系;例如很多用户有相同的角色名,但一个用户只能有一个角色名;这里角色名就是“一”,用户就是“多”。

  • 创建:在作为“一”的一方写关联。

创建roles表和users表之间的关联,我只需要修改类Role的定义就可以了。

class Role(db.Model):__tablename__ = 'roles'id = db.Column(db.Integer, primary_key=True)name = db.Column(db.String(16), unique=True)# 在"一"的一方,写关联# Role表增加了一个users属性# backref='role':表示role也是User要用的属性(回关)users = db.relationship('User', backref='role')

关联的属性不会出现在数据库的表中,我们可以通过类名.属性名的方式来访问一个表的属性,例如

print(ro1.users)

输出的效果是这样子(下面的输出仅用于展示格式),它仅显示了类型和id,

[<User 1>, <User 2>]

如果我希望显示用户的具体信息,则需要在类的定义中加入__ref__方法,例如在类User中加入,

class User(db.Model):__tablename__ = 'users'id = db.Column(db.Integer, primary_key=True)name = db.Column(db.String(16), unique=True)email = db.Column(db.String(32),unique=True)password = db.Column(db.String(32))role_id = db.Column(db.Integer, db.ForeignKey('roles.id'))# 类的实例返回字符串def __repr__(self) -> str:return '<User: %s %s %s %s %s>' % (self.id, self.name, self.email, self.password, self.role_id)

则表的属性显示效果将是

[<User: 1 wang wang@123.com None 1>, <User: 2 zhang zhang@123.com None 1>]

4、查询——通过SQLAlchemy扩展

过滤器和执行器,过滤器仅对数据进行筛选,返回结果还需使用执行器。

查询users表中的所有对象

User.query.all()

查询users表中id为4的对象

# 1. 旧的,已弃用
User.query.get(4)
# 2. filter_by --> 属性=值
User.query.filter_by(id=4).first()
# 3. filter --> 类.属性==值; 更加灵活,支持比较运算符
User.query.filter(User.id==4).first()

5、其他

1. 数据模型的实现(疑惑)

感觉有些奇怪,在定义一个数据模型类时,我仅仅需要在类中定义一些变量,如__tablename__idname

class Role(db.Model):__tablename__ = 'roles'id = db.Column(db.Integer, primary_key=True)name = db.Column(db.String(16), unique=True)

后面创建数据时就可以使用这些变量名作为关键字参数传参,

ro1 = Role(name='admin')

我不知道父类db.Model做了什么可以达到这样的效果,可能我python还是学得太浅了叭。

6、Bug记录

1. 1045,"Access denied for user ‘root’@‘localhost’ "(using password: YES)

当时我在cmd可以登录数据库,可当我运行python脚本时,就报出这个错误,查了许多文章都没有解决。后来有次在终端输错了密码发现也是报这个错误,于是发现是配置数据库地址的问题,

root:mysql中的mysql是密码,我还以为是固定的语法就照写了。

# 错误写法
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://root:mysql@127.0.0.1/flask_sql_demo2'
# 修改
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://root:我的密码@127.0.0.1/flask_sql_demo2'

2. RuntimeError: Working outside of application context

发现脚本中对数据库的操作就会引发改问题,一个较方便的处理方式是

ctx = app.app_context()
ctx.push()
数据库操作
ctx.pop()

参考:解决Flask中RE

参考文章中还有一种使用with的上下文管理,也是可以哒。


http://www.lryc.cn/news/6012.html

相关文章:

  • 牛客网Python篇数据分析习题(六)
  • Ansible的安装及部署
  • 链表题目总结 -- 递归
  • 重写-linux内存管理-伙伴分配器(一)
  • 为什么要用springboot进行开发呢?
  • 设备树信息解析相关函数
  • LeetCode-1124. 表现良好的最长时间段【哈希表,前缀和,单调栈】
  • vue-router路由配置
  • 中国计算机设计大赛来啦!用飞桨驱动智慧救援机器狗
  • 嘉定区2022年高新技术企业认定资助申报指南
  • 【C++】关键字、命名空间、输入和输出、缺省参数、函数重载
  • 【一道面试题】关于HashMap的一系列问题
  • 论文笔记: Monocular Depth Estimation: a Review of the 2022 State of the Art
  • Springmvc补充配置
  • MySQL 的 datetime等日期和时间处理SQL函数及格式化显示
  • 基于微信云开发的防诈反诈宣传教育答题小程序
  • Map和Set
  • 【位运算问题】Leetcode 136、137、260问题详解及代码实现
  • 同花顺2023届春招内推
  • 深入Kafka核心设计与实践原理读书笔记第三章消费者
  • IDEA 中使用 Git 图文教程详解
  • 【Linux系统】进程概念
  • 上课睡觉(2023寒假每日一题 4)
  • 【Selenium学习】Selenium 中常用的基本方法
  • python练习——简化路径
  • 2023新华为OD机试题 - 火星文计算2(JavaScript) | 刷完必过
  • 前端插件重磅来袭
  • 深入工厂|高精密多层板是如何被智造出来的?
  • 代理模式动态代理
  • Mysql之二进制日志