1.创建数据库
from sqlalchemy.ext.declarative import declarative_base from sqlalchemy import Column, Integer, String, ForeignKey, UniqueConstraint, Index from sqlalchemy.orm import sessionmaker, relationship from sqlalchemy import create_engine engine = create_engine("mysql+pymysql://root:Passw0rd!@192.168.2.101/beadata", max_overflow=5) Base = declarative_base() class Test(Base): __tablename__ = 'Test' nid = Column(Integer,primary_key=True,autoincrement=True) name = Column(String(32)) class Group(Base): __tablename__ = 'Group' nid = Column(Integer,primary_key=True,autoincrement=True) caption = Column(String(32)) class User(Base): __tablename__ = 'User' nid = Column(Integer,primary_key=True,autoincrement=True) username = Column(String(32)) group_id = Column(Integer,ForeignKey('Group.nid')) def init_db(): Base.metadata.create_all(engine) # def drop_db(): # Base.metadata.drop_all(engine) init_db()
执行init_db创建一个数据库的对象(数据库必须存在),创建了上面的三张表。需要执行操作,要创建session
Session = sessionmaker(bind=engine)
session = Session()
然后利用session来增加数据:
session.add(Group(caption='dba')) session.add(Group(caption='dvd')) session.add_all([ User(username='alex4',group_id='4'), User(username='alex5',group_id='5'), User(username='alex6',group_id='6'), ]) session.commit()
插入的时候报键值对错误。
2.单表查询,得到的结果是一个列表的对象
ret = session.query(User).filter(User.username == 'alex1').all() print (ret) print (ret[0].nid,ret[0].username,ret[0].group_id)
[<__main__.User object at 0x000000000375CA20>]
1 alex1 1
需要注意的是,我们的ret返回的时候其实是一个列表的对象,那么如何能返回我们看到的数据呢?在SQLAlchemy中,我们定义了__repr__的方法,重写__repr__方法后,每次返回的就不是对象而是看到的数据了。
class User(Base): __tablename__ = 'User' nid = Column(Integer,primary_key=True,autoincrement=True) username = Column(String(32)) group_id = Column(Integer,ForeignKey('Group.nid')) def __repr__(self): temp = "[%s --- %s --- %s]"%(self.nid,self.username,self.group_id) return temp
返回结果:
[[1 --- alex1 --- 1], [2 --- alex2 --- 2]]
3.一对多之正向查找与反向查找
我们设计两张表:
Group表:
nid | caption |
1 | dba |
2 | dvd |
3 | sic |
User表:
nid | username | group_id |
1 | alex1 | 1 |
2 | alex2 | 1 |
15 | alex1 | 2 |
16 | alex1 | 1 |
在数据中,JOIN操作得到的结果如下:
JOIN: sql = session.query(User).join(Group) print(sql) ret = session.query(User).join(Group).all() print (ret)
结果:
SELECT "User".nid AS "User_nid", "User".username AS "User_username", "User".group_id AS "User_group_id" FROM "User" JOIN "Group" ON "Group".nid = "User".group_id [[1 --- alex1 --- 1], [2 --- alex2 --- 1], [15 --- alex1 --- 2], [16 --- alex1 --- 1]]
User LEFT JOIN Group
sql = session.query(User).join(Group,isouter=True) print(sql) ret = session.query(User).join(Group,isouter=True).all() print (ret)
SELECT "User".nid AS "User_nid", "User".username AS "User_username", "User".group_id AS "User_group_id" FROM "User" LEFT OUTER JOIN "Group" ON "Group".nid = "User".group_id [[1 --- alex1 --- 1], [2 --- alex2 --- 1], [15 --- alex1 --- 2], [16 --- alex1 --- 1]]
Group LEFT JOIN User
sql = session.query(Group,User.username).join(User,isouter=True)
print(sql)
ret = session.query(Group,User.username).join(User,isouter=True).all()
print (ret)
SELECT "Group".nid AS "Group_nid", "Group".caption AS "Group_caption", "User".username AS "User_username"
FROM "Group" LEFT OUTER JOIN "User" ON "Group".nid = "User".group_id
[([1 --- dba], 'alex1'), ([1 --- dba], 'alex2'), ([2 --- dvd], 'alex1'), ([3 --- sic], None)]
正向查找:
传统形式下,我们要查找用户'alex2'属于哪个组,需要执行下面的命令:
ret = session.query(User.username,Group.caption).join(Group).filter(User.username == 'alex2').all() print (ret)
执行结果:
[('alex2', 'dba')]
但在新方法下面:
ret = session.query(User).filter(User.username == 'alex2').all() for obj in ret: print (obj.nid,obj.username,obj.group,obj.group.caption)
执行结果:
2 alex2 [1 --- dba] dba
原因在于,在'User'表中有如下的定义
group = relationship("Group", backref='uuu')
表示的意思是在'User'表中隐性的添加了一列叫做'group',这一列表示的就是表中数据是属于'Group'中的那一个组的对应关系,它返回的是一个对象,因此可以使用obj.group.caption来访问'Group'中的数据。
=================================================================================================
反向查找:
传统形式下,我们需要获取到'dba'这个角色的内容,需要执行下面的命令:
ret = session.query(User.username,Group.caption).join(Group,isouter=True).filter(Group.caption == 'dba').all() print (ret)
执行结果:
[('alex1', 'dba'), ('alex2', 'dba'), ('alex1', 'dba')]
但是在新方法下面:
obj = session.query(Group).filter(Group.caption == 'dba').all() for item in obj: print (item.uuu)
执行结果:
[[1 --- alex1 --- 1], [2 --- alex2 --- 1], [16 --- alex1 --- 1]]
原因在于,在于外键在同一个类的定义里面,有如下的说明:
class User(Base): __tablename__ = 'User' nid = Column(Integer,primary_key=True,autoincrement=True) username = Column(String(32)) group_id = Column(Integer,ForeignKey('Group.nid')) group = relationship("Group", backref='uuu') def __repr__(self): temp = "[%s --- %s --- %s]"%(self.nid,self.username,self.group_id) return temp
这相当于定义了在User表中添加了一个字段为group,这个字段记录了用户对应的组,而'uuu'则相当于在表Group中每一行中添加了一个列表,内容是属于这个组的各个用户的数据。