文章目录
- 一、Python数据库连接方式
- 1、python的两种数据库连接方式:
- 2、ORM是什么?有什么优势?
- 二、什么是Flask-SQLAlchemy?
- 三、如何配置数据库
- 1、安装第三方模块
- 2、数据库配置
- 四、定义模型
- 1、数据库模型
- 2、模型列类型
- 3、模型列属性
- 4、数据查询
- 1)查询过滤器
- 2)查询执行函数
- 五、数据库关系
- 1、一对一关系
- 1)模型定义
- i、定义公民
- ii、定义身份证
- iii、关联身份证和公民
- 2)基本操作
- 2、一对多关系
- 1)模型定义
- i、定义学生
- ii、定义班级
- iii、建立关联
- 2)基本操作
- 3、多对多关系
- 1)模型定义
- i、定义学生
- ii、定义课程
- iii、建立关联表
- 2)基本操作
一、Python数据库连接方式
1、python的两种数据库连接方式:
- Python 标准数据库接口,使用 SQL 语句正常操作数据库。
e.g: MySQL 关系型数据库的 pymsql 模块 - 用 ORM 来进行数据库连接, Python 中使用sqlalchemy , flask中典型的 flask_sqlalchemy ,以面向对象的方式进行数据库的连接与操作
2、ORM是什么?有什么优势?
ORM ,即 Object-Relational Mapping (对象关系映射),它的作用是在关系型数据库和业务实体对
象之间作一个映射,这样,我们在具体的操作业务对象的时候,就不需要再去和复杂的 SQL 语句打交道,只需简单的操作对象的属性和方法。
图片解析:
使用对象关系映射时,面对不同的数据库不需要使用特定的数据库语言,使用简单的面向对象语言,比如python,通过OR Mapper和SQL Alchemy引擎将面向对象语言转换为对应的数据库语言如SQL等,对数据库中的数据进行处理,并且返回给用户的只是成功失败等结果。
二、什么是Flask-SQLAlchemy?
- Flask-SQLAlchemy 是一个 Flask 扩展,简化了在 Flask 程序中使用 SQLAlchemy 的操作。
- SQLAlchemy 是一个很强大的关系型数据库框架,支持多种数据库后台。
SQLAlchemy 提供了高层 ORM ,也提供了使用数据库原生 SQL 的低层功能。
三、如何配置数据库
1、安装第三方模块
pip install -i https://pypi.douban.com/simple flask-sqlachemy
2、数据库配置
#获取当前文件的绝对路径
import os
basedir=os.path.abspath(os.path.dirname(__file__))
#用于连接数据的数据库
SQLALCHEMY_DATABASE_URI='sqlite:///'+os.path.join(basedir,'data.sqlite')
#print(SQLALCHEMY_DATABASE_URI)
#sqlite:///D:\python课外学习\Web前端\Flsak\mycode\day4_sqlachemy数据库操作实现\data.sqlite
#sqlalchemy是否追踪对象的修改并且发送信息
SQLALCHEMY_TRACK_MODIFICATIONS=False
#每次请求结束之后自动提交数据库的变动
SQLALCHEMY_COMMIT_ON_TEARDOWN=True
配置文件完成后,需要导入到主函数文件run.py中
app.config.from_pyfile('config.py')
#从配置文件中导入数据库的配置
- 流行的数据库引擎采用的数据库 URL格式
- 连接mysql数据库报错信息
import pymysql
pymysql.install_as_MySQLdb()
四、定义模型
1、数据库模型
from run import db
#数据库连接:db.Model--一个数据库模型
"""
create table users(id int primary_key,name varchar(20) unique);
"""
class User(db.Model):
__tablename__='users'
id=db.Column(db.Integer,autoincrement=True,primary_key=True)
name=db.Column(db.String(20),unique=True)
if __name__ == '__main__':
#创建模型文件中定义的数据库表,一个类对应一个数据库表
db.create_all()
#添加用户信息到users表中
user=User(name='anan2')
#1.添加到会话中
db.session.add(user)
#2.提交到数据库中
db.session.commit()
#查询数据库操作:filter_by根据姓名筛选用户信息,.first()获取列表中的第一个对象
user=User.query.filter_by(name='anan').first()
print('查询用户的信息:',user.id,user.name)
#删除用户信息:要删除谁
db.session.delete(user)
db.session.commit()
#修改用户信息:类似于添加
user=User.query.filter_by(name='anan').first()
user.name='yuyu'
db.session.add(user)
db.session.commit()
2、模型列类型
类型名 | python类型 | 说明 |
Integer | int | 普通整数,一般是32位 |
SmallInteger | int | 取值范围小的整数,一般是16位 |
BigInteger | int或long | 不限制精度的整数 |
Float | float | 浮点数 |
Numeric | decimal.Decimal | 定点数 |
String | str | 变长字符串 |
Text | str | 变长字符串,对较长或不限长度的字符串做了优化 |
Unicode | unicode | 变长Unicode字符串 |
UnicodeText | unicode | 变长Unicode字符串,对较长或不限长度的字符串做了优化 |
Boolean | bool | 布尔值 |
Date | datetime.date | 日期 |
Time | datetime.time | 时间 |
DateTime | datetime.datetime | 日期和时间 |
Interval | datetime.timedelta | 时间间隔 |
Enum | str | 一组字符串 |
PickleType | 任何python对象 | 自动使用Pickle序列化 |
LargeBinary | str | 二进制文件 |
3、模型列属性
选项名 | 说明 |
primary_key | 如果设为True,这列就是表的主键 |
unique | 如果设为True,这列不允许出现重复的值 |
index | 如果设为True,为这列创建索引,提升查询效率 |
nullable | 如果设为True,这列允许使用空值;如果设为False,这列不允许设置空值 |
default | 为这列定义默认值 |
4、数据查询
1)查询过滤器
过滤器 | 说明 |
filter() | 把过滤器添加到原查询,返回新查询 |
filter_by() | 把等值过滤器添加到原查询,返回新查询 |
limit() | 使用指定值限制原查询返回的结果数量,返回新查询 |
offset() | 偏移原查询返回的结果,返回新查询 |
order_by() | 排序返回结果,返回新查询 |
groupby() | 原查询分组,返回新查询 |
2)查询执行函数
方法 | 说明 |
all() | 以列表形式返回结果 |
first() | 返回第一个结果,如果没有返回None |
first_or_404() | 返回第一个结果,如果没有抛出404异常 |
get() | 返回主键对应记录,没有则返回None |
get_or_404() | 返回主键对应记录,如果没有抛出404异常 |
count() | 返回查询结果数量 |
paginate() | 返回paginate对象,此对象用于分页 |
五、数据库关系
数据库实体间有三种对应关系:一对一,一对多,多对多。
1、一对一关系
一个学生对应一个学生档案材料,或者每个人都有唯一的身份证编号。
1)模型定义
i、定义公民
class People(db.Model):
__tablename__ = 'peoples'
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
name = db.Column(db.String(20), nullable=False)
age=db.Column(db.Integer,default=18)
def __init__(self,name):
self.name=name
def __repr__(self):
return '<People:%s>'%(self.name)
ii、定义身份证
class Card(db.Model):
__tablename__ = 'cards'
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
cardID = db.Column(db.String(30), nullable=False)
is_valid=db.Column(db.Boolean,default=True)
def __repr__(self):
return '<Card:%s>'%(self.name)
iii、关联身份证和公民
在公民类中添加:
#将公民和身份证关联起来,uselist=False指的是一个对象不对应一个列表,因此此时是一对一关系
#backref='People'指,在Card类里面添加属性信息名称为people,可以根据身份证获取用户公民信息
card=db.relationship('Card',backref='people',uselist=False)
在身份证中添加:
#添加外键是为了在用id对应公民时,是一一对应的而不是随便对应。'peoples'指的是表的名称
people_id=db.Column(db.Integer,db.ForeignKey('peoples.id'))
2)基本操作
if __name__ == '__main__':
db.create_all()
#增加
p1=People(name='张三')
p2=People(name='李四')
c1=Card(cardID='001')
c2=Card(cardID='002')
# p1.card=c1
# p2.card=c2
c1.people=p1
c2.people=p2
db.session.add_all([p1,p2,c1,c2])
db.session.commit()
#删除
Card.query.get(1)
db.session.delete(c1)
db.session.commit()
2、一对多关系
一个学生只属于一个班,但是一个班级有多名学生。
- 设计数据库表:只需在学生表中多添加一个班级号的ID;
- 通过添加主外键约束,避免删除数据时造成数据混乱。
1)模型定义
i、定义学生
class Student(db.Model):
__tablename__ = 'students'
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
name = db.Column(db.String(20), nullable=False)
ii、定义班级
class Grade(db.Model):
__tablename__ = 'grades'
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
name = db.Column(db.String(20), nullable=False)
iii、建立关联
在学生中添加外键:
#外键关联
grade_id=db.Column(db.Integer,db.ForeignKey('grades.id'))
在班级中:
#关系,backref='grade'指Student类中添加属性grade,userlist=True指一对多关系,即一个对象对应一个列表
students=db.relationship('Student',backref='grade')
2)基本操作
if __name__ == '__main__':
db.create_all()
#增加
s1=Student(name='张三')
s2=Student(name='李四')
s3=Student(name='王五')
grade1=Grade(name='python开发')
grade2=Grade(name='Linux运维')
grade1.students=[s1,s2,s3]
db.session.add_all([s1,s2,s3,grade1,grade2])
db.session.commit()
#删除
grade1=Grade.query.get(1)
db.session.delete(grade1)
db.session.commit()
3、多对多关系
一个学生可以选择多门课,一门课也有多名学生。
- 对于多对多表,通过关系表就建立起了两张表的联系。
- 多对多表时建立主外键后,要先删除约束表
内容再删除主表内容。
1)模型定义
i、定义学生
class MathStudent(db.Model):
__tablename__ = 'math_students'
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
name = db.Column(db.String(20), nullable=False)
#关联,secondary=tags指定关系表对象
courses=db.relationship('Course',secondary=tags)
def __repr__(self):
return "<MathStudent: %s >" % (self.name)
ii、定义课程
class Course(db.Model):
__tablename__ = 'courses'
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
name = db.Column(db.String(20), nullable=False)
#关联
students=db.relationship('MathStudent',secondary=tags)
def __repr__(self):
return "<Course: %s >" % (self.name)
iii、建立关联表
#多对多关系,第三方表
tags=db.Table('tags',
db.Column('student_id',db.Integer,db.ForeignKey('math_students.id')),
db.Column('course_id',db.Integer,db.ForeignKey('courses.id')))
2)基本操作
if __name__ == '__main__':
db.create_all()
#增加
# s1=MathStudent(name="拉格朗日")
# s2=MathStudent(name="麦克劳林")
# s3=MathStudent(name="罗尔")
# course1=Course(name="高等数学")
# course2=Course(name="线性代数")
#
# s1.courses.append(course1)
# s1.courses.append(course2)
# s2.courses.append(course1)
# s3.courses.append(course2)
#
# course1.students.append(s3)
#
# db.session.add_all([s1,s2,s3,course1,course2])
# db.session.commit()
#删除
courseObj=Course.query.filter_by(name="线性代数").first()
studentObj=MathStudent.query.filter_by(name="罗尔").first()
print("删除前选择线性代数的学生: ", courseObj.students)
courseObj.students.remove(studentObj)
print("删除后择线性代数的学生: ", courseObj.students)