SQLAlchemy-ORM
1. MVT
M model 模型
V view 视图
T template 模板
客户端请求---》view----》model-----》view----》template--->view----->客户端
查数据 渲染
2. Flask表关系-一对一
addresses = relationship("Address", backref='addresses', uselist=False)
一对一其实是一对多的特殊情况,从一对多的是实例发现,一对应的是User表,而多对应的是address,也就是说一个User对象有多个address。
class User(Base):
__tablename__ = 'users'
id = Column(Integer,primary_key=True)
name = Column(String(50))
fullname = Column(String(50))
password = Column(String(100))
addresses = relationship("Address",backref='addresses',uselist=False)
class Address(Base):
__tablename__ = 'addresses'
id = Column(Integer,primary_key=True)
email_address = Column(String(50))
user_id = Column(Integer,ForeignKey('users.id')
user = relationship('Address',backref='user')
3. flask表关系-多对多
# 创建中间表格
teacher_classes = Table(
'teacher_classes',
Base.metadata,
Column('teacher_id', Integer, ForeignKey('teacher.id')),
Column('classes_id', Integer, ForeignKey('classes.id'))
)
# 模型中
classes = relationship('Classes', backref='teachers', secondary=teacher_classes)
多对多需要一个中间来作为连接,同理在slalchemy中的orm也需要一个中间表,假如现在有一个Teacher和一个Classes表,即老师和班级,一个老师可以教多个班级,一个班级有多个老师,是一种典型的多对多关系,那么通过sqlalchemy的ORM的实现方式
1.association_table = Table(
2. 'teacher_classes',
3. Base.metadata,
4. Column('teacher_id',Integer,ForeignKey('teacher.id')),
5. Column('classes_id',Integer,ForeignKey('classes.id'))
6. )
7.
8.class Teacher(Base):
9. __tablename__ = 'teacher'
10. id = Column(Integer,primary_key=True)
11. tno = Column(String(10))
12. name = Column(String(50))
13. age = Column(Integer)
14. classes = relationship('Classes',secondary=association_table,backref='teachers')
15.
16.class Classes(Base):
17. __tablename__ = 'classes'
18. id = Column(Integer,primary_key=True)
19. cno = Column(String(10))
20. name = Column(String(50))
21. teachers = relationship('Teacher',secondary=association_table,backref='classes')
要创建一个多对多的关系表,首先需要一个中间表,通过Table来创建一个中间表。上例中间第一个参数teacher_classes代表的是中间表,第二个参数是Base的元素,第三个和第四个参数就是要连接的二个表,其中Column第一个参数是表示的是连接表的外键名,第二个参数表示这个外键的类型,第三个参数表示要外键的表名和字段。
4. 数据库排序
1、order_by:可指定根据这个表中的某个字段进行排序,如在前面加一个-,代表的是降序排序。
2、在模型定义的时候指定默认排序:有些时候,不想每次在查询的时都指定排序的方式,可以在定义模型时指定排序的方式。
在模型定义中,添加以下代码
1. __mapper_args__ = {
2. "order_by": title
3. }
。即可让文章使用标题来进行排序。
3.正向排序和反向排序:默认情况是从小到大,从前到后排序的,如想要反向排序,可以调用排序的字段desc方法。
。limit 限制查询条数
。limit:可限制每次查询时只查几条数据。
。offset:可限制查找数据时过滤掉前面多少条。 从哪里开始(类似于索引)
。切片:可对Query对象使用切片操作,来获取想要的数据。(和数据类型切片一样)
5. 高级查询和子查询
group_by 进行分组 通常和聚合函数配合使用。根据某个字段进行分组。比如想要根据性别进行分组,来统计每个分组分别有多少人
1.session.query(User.gender,func.count(User.id)).group_by(User.gender).all()
having 新查询之后的数据集还想通过限制条件来查询,就需要用到having来做限制。
having是对查找结果进一步过滤。比如只想要看未成年人的数量,那么可以首先对年龄进行分组统计人数,延后再对分组进行having过滤。
1.result = session.query(User.age,func.count(User.id)).group_by(User.age).having(User.age >= 18).all()
join方法
join查询分为二种,一种是inner join,默认的是inner join。另一种是Outer join。默认的是inner join,如果指定left join 或者是right join则为outer join。如果想要查询User及其对应的Address,则可以通过以下方式来实现
1. for u,a in session.query(User,Address).filter(User.id==Address.user_id).all():
2. print(u)
3. print(a)
如果采用outer join,可以获取所有user,而不用在乎这个user是否有address对象,并且outer join默认为左外查询:
1. for instance in session.query(User,Address).outerjoin(Address).all():
2. print(instance)
别名:
当多表查询时,有时同一个表要用到多次,这时用别名就可以方便解决命名冲突的问题了:
1 from sqlalchemy.orm import aliased
2 adalias1 = aliased(Address)
3 adalias2 = aliased(Address)
4 for username,email1,email2 in session.query(User.name,adalias1.email_address,adalias2.email_address).join(adalias1).join(adalias2).all():
5 print(username,email1,email2)
子查询
sqlachemy 也支持子查询,如现在要查找一个用户的用户名及该用户的邮箱地址数量。要满足这个需求,可以在子查询中找到所有用户的邮箱数(通过group by合并同一用户),然后再将结果放在父查询中进行使用:
1 from sqlalchemy.sql import func
2 # 构造子查询
3 stmt = session.query(Address.user_id.label('user_id'),func.count(*).label('address_count')).group_by(Address.user_id).subquery()
4 # 将子查询放到父查询中
5 for u,count in session.query(User,stmt.c.address_count).outerjoin(stmt,User.id==stmt.c.user_id).order_by(User.id):
6 print u,count
从上面看到,一个查询如果想要变成子查询,则是通过subquery()方法实现,变成子查询后,通过子查询.c属性来访问查询出来的列。以上方法只能查询某个对象的具体字段,如要查找整个实体,则想需要通过aliased方法
1 stmt = session.query(Address)
2 adalias = aliased(Address,stmt)
3 for user,address in session.query(User,stmt).join(stmt,User.addresses):
4 print user,address