Flask-SQLAchemy教程
SQLALchemy, ORM框架(详细点我)
作用: 帮助我们使用类和对象快速实现数据库操作。
数据库:
- 原生:
- MySQLdb
-不支持python3
- pymysql
-支持python 3/2
- ORM框架
- SQLAlchemy
创建表
<pre class="brush:python;gutter:true;">import datetime
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column,UniqueConstraint
from sqlalchemy import Integer,String,DateTime,ForeignKey
from sqlalchemy.orm import relationship
from engine import engine
Base = declarative_base()
#类名就相当于表名
class Userinfo(Base):
__tablename__ = 'userinfo'
id = Column(Integer, primary_key=True, autoincrement=True)
name = Column(String(32),index=True,nullable=True)
pwd = Column(Integer,nullable=True)
dept_id = Column(Integer,ForeignKey('dept.id'))
c_time = Column(DateTime,default=datetime.datetime.now())
#在表里面不生成字段,就是方便查询和添加数据用
dp = relationship('Dept', backref='us')
class Dept(Base):
__tablename__ = 'dept'
id = Column(Integer, primary_key=True, autoincrement=True)
name = Column(String(32),index=True,nullable=True)
#创建多对多的关系的时候,SQLAlchemy没有ManytoMany的字段,
# 就不能帮我们自动的生成第三张表,而是要靠我们自己去创建第三张表,来记录关系
#学生和课程是多对多关系的
class Student(Base):
__tablename__ = 'student'
id = Column(Integer, primary_key=True, autoincrement=True)
name = Column(String(32), index=True, nullable=True)
cdp = relationship('Course',secondary='student2course',backref='sdp')
class Course(Base):
__tablename__ = 'course'
id = Column(Integer, primary_key=True, autoincrement=True)
name = Column(String(32), index=True, nullable=True)
class Student2Course(Base):
__tablename__ = 'student2course'
id = Column(Integer, primary_key=True, autoincrement=True)
student_id = Column(Integer,ForeignKey('student.id'))
course_id = Column(Integer,ForeignKey('course.id'))
__table_args__ = (
#联合唯一
UniqueConstraint('student_id', 'course_id', name='sc_id'),
#联合
# Index('ix_id_name', 'name', 'extra'),
)
#根据类创建数据库,需要数据库的连接
def create_all():
Base.metadata.create_all(engine)
def drop_all():
Base.metadata.drop_all(engine)
if __name__== '__main__':
# drop_all()
create_all()
连接数据库
<pre class="brush:python;gutter:true;">from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker,scoped_session
engine = create_engine(
'mysql+pymysql://root:[email protected]:3306/sqlalchemydb?charset=utf8',
max_overflow = 0,
pool_size = 5,
pool_timeout = 10,
pool_recycle = -1,
)
#也需要要数据的连接
SessionFactory = sessionmaker(bind=engine)
# scoped_session 是基于 threading.local();从连接池中取一个连接放入自己的线程的空间里面
# 所以多个线程,并发的时候,也是为每个线程自己的空间内有自己的一条连接,这样就不冲突了。
session = scoped_session(SessionFactory)
#按照session = SessionFactory() 这样的形式的时候,在每一次线程来的时候,
# 都需要每次都从连接池中获取连接
'''
def task():
session = SessionFactory()
session.query(Student).all()
session.close()
from threading import Thread
for i in range(20):
t = Thread(target=task)
t.start()
'''
'''
session = scoped_session(SessionFactory)
def task():
session.query(Student).all()
session.remove() 把自己线程空间内的连接删除掉。也就是将连接返回给连接池。
from threading import Thread
for i in range(20):
t = Thread(target=task)
t.start()
'''
对表的操作
<pre class="brush:python;gutter:true;">from SQLAlchemy_Demo import Userinfo,Dept,Student,Student2Course,Course
from engine import session
from sqlalchemy.orm import sessionmaker
#操作用sqlalchemy生成的表
# ############# 执行ORM操作 #############
#查询
#filter()里面是一个表达式
#filter_by()里面是关键字传参数了
# ret = session.query(Userinfo).filter(Userinfo.id>2).all()
# ret = session.query(Userinfo).filter_by(id=2).first()
# print(ret)
#增加数据
#一个对象就代表着一行数据
# obj = Userinfo(name='alex',pwd=123,dept_id=1)
# session.add(obj)
#批量的添加数据
# session.add_all([
# Userinfo(name='db',pwd=123,dept_id=1),
# Userinfo(name='xiaodong',pwd=123,dept_id=1),
# ])
# session.commit()
# session.close()
#删除 .delete()
# session.query(Userinfo).filter(Userinfo.id >3).delete()
# session.commit()
# session.close()
#修改 update({})
# session.query(Userinfo).filter(Userinfo.id ==1).update({"name":"阿辉"})
#synchronize_session=False就可以字符串的拼接了;默认的是数字的拼接。; Userinfo.name可以用表里面的数据
# session.query(Userinfo).filter(Userinfo.id ==1).update({Userinfo.name:Userinfo.name+'帅逼'},synchronize_session=False)
# session.query(Userinfo).filter(Userinfo.id ==1).update({Userinfo.pwd:Userinfo.pwd+999})
# session.commit()
# session.close()
#常用的操作
# 分组 后面跟条件 having
# from sqlalchemy.sql import func
# ret = session.query(Userinfo).group_by(Userinfo.extra).all()
#上面这查不了,因为分组后每组后多个,不知道给你返回哪一个,需要你自己来指定。
# ret = session.query(
# func.max(Userinfo.id),
# ).group_by(Userinfo.dept_id).having(func.max(Userinfo.id) >2).all()
# print(ret)
#FK 连表操作 query要查询哪张表里面的什么数据
# on 条件 Userinfo.dept_id == Dept.id #join -- inner join
# user_data = session.query(Userinfo.id,Userinfo.name.label('username'),Dept.name).join(Dept,Userinfo.dept_id == Dept.id).all()
# isouter=True -- > LEFT OUTER JOIN -- LEFT JOIN
# user_data = session.query(Userinfo.id,Userinfo.name.label('username'),Dept.name).join(Dept,Userinfo.dept_id == Dept.id,isouter=True).all()
# for item in user_data:
# print(item.id,item.username,item.name)
# print(session.query(Userinfo.id,Userinfo.name.label('username'),Dept.name).join(Dept,Userinfo.dept_id == Dept.id,isouter=True))
# ret = session.query(Dept).filter(Dept.name == '销售').first()
# print(ret)
#FK关系表
#创建一个名称为: IT部门,再在该部门中添加一个员工:小光
#第一种方式:
# dept_obj = Dept(name='IT部门')
# session.add(dept_obj)
# session.commit()
#只要commit后 dept_obj这个创建的对象就是当前添加到表里面的对象
# dept_id = dept_obj.id
# print(dept_id)
# user_obj = Userinfo(name='小光',dept_id=dept_id,pwd=123)
# session.add(user_obj)
# session.commit()
# session.close()
#第二种通过relation字段
# user_obj = Userinfo(name='小光',pwd=123,dp=Dept(name='IT部门'))
#
# session.add_all(user_obj)
# session.commit()
#创建一个名称为: IT部门,再在该部门中添加一个员工:小2,小3,小4
#以上的这种简单的方法就不可取了。
#user_obj = Userinfo(name='小光',pwd=123,dp=Dept(name='IT部门'))
# user_objs = Userinfo(name='小光02',pwd=123,dp=Dept(name='IT部门'))
#这样就生成了两个IT部门,分别在对应的添加人。
#这样要通过反向生成了
# obj=Dept(name='IT部门01')
# obj.us = [Userinfo(name='小2',pwd=123),Userinfo(name='小3',pwd=123)]
#
# session.add(obj)
#
# session.commit()
# session.close()
#ManytoMany 多对多关系表
#添加上python课程的小辉和小黑,上Linux的小黑,以及上go的小龙到数据库中
#方式一,自己添加到三张表中
# session.add_all([Student(name='小辉'),Student(name='小黑'),Student(name='小龙')])
# session.add_all([Course(name='Python'),Course(name='Linux'),Course(name='go')])
# session.add_all([Student2Course(student_id=6,course_id=6),Student2Course(student_id=7,course_id=6),Student2Course(student_id=7,course_id=7),Student2Course(student_id=8,course_id=8)])
# session.commit()
# session.close()
#方式二:
# 创建一个新的课程,创建2个学生,并且为两个学生选取新创建的课程
# c_obj = Course(name='java')
# c_obj.sdp =[Student(name='01'),Student(name='02')]
#
# session.add(c_obj)
#帮我们在三张表中创建数据
# session.commit()
# session.close()
#正常查询的话,需要自己不断的连表
#查询上python课程的所有学生的姓名
# p_obj = session.query(Student2Course.student_id,Course.name,Student.name).join(Course,Student2Course.course_id ==Course.id).join(Student,Student2Course.student_id == Student.id).filter(Course.name=='python').all()
# print(p_obj)
# 上面的查询需要自己连表,比较麻烦 因此用relationship字段来查询,跟FK的相似。
c_obj = session.query(Course).filter(Course.name=='python').first()
ret = c_obj.sdp
for item in ret:
print(item.name)