Flask-SQLAlchemy查询方法汇总 - 表间查询 一对一、一对多、多对多

1. 一对一
参考一对多的例子,下添加uselist=False就变成了一对一。

# 添加一对一的反向引用,在一对多的情况下添加uselist=False就变成了一对一
    rank_related_score = db.relationship('tbl_2018_data', 
        backref = 'score_related_rank', uselist=False)

2. 一对多

例子,如下的模型:

class Role(db.Model):
    __tablename__ = 'roles'
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(64), unique=True) 
    
    # 在此申明Role类与User类具备指向关系,且具体的关联是通过外键db.ForeignKey这个绑定的
    role_related_user = db.relationship('User', backref='student_related_role', lazy='dynamic')
    
    def __repr__(self):     
        return '<Role %r>' % self.name 
        

class User(db.Model):
    __tablename__ = 'users'
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(64), unique=True, index=True)
    # 指定role_id这个字段来源于Roles表格的外键,指向方式:表名 + 字段名(表名)
    role_id = db.Column(db.Integer, db.ForeignKey('roles.id'))
    
    def __repr__(self): 
        return '<User %r>' % self.username

role_related_user 描述了:User和Role的关系

第一个参数:为对应参照的类名"User"
第二个参数:backref为类Students申明新的属性(这个属性方便在2个表格之间互相指向)
第三个参数:lazy决定了什么时候SQLALchemy从数据库中加载数据

lazy的用法:
- select:就是访问到属性的时候,就会全部加载该属性的数据。跳转到另一个表格如果是多的一方,直接使用指向属性就行,不需要使用one(),all()等函数
- joined:对关联的两个表使用联接
- subquery:与joined类似,但使用子查询
- dynamic:生成query对象列表,跳转另一个表格如果对应多的一方,需要使用one(),all(),first() 等方法获取到这个对象,然后才能取到对应的属性值。跳转到另一个表格,如果对应少的一方,循环之后直接使用属性就能获取属性值

代码:

key = "steven"
user_query_result = User.query.filter_by(username=key).first()
related_role_class = user_query_result.student_related_role.className
# user_query_result.student_related_role 会跳转到 Role 表

  1. 多对多
from flask_sqlalchemy import SQLAlchemy
from APP.app import app

db = SQLAlchemy(app)

association_table = db.Table('association',
                             db.Column('id', db.Integer, primary_key=True, autoincrement=True),
                             db.Column('customer_id', db.Integer, db.ForeignKey('customer.id')),
                             db.Column('product_id', db.Integer, db.ForeignKey('product.id'))
                             )


class Customer(db.Model):
    __tablename__ = 'customer'
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    name = db.Column(db.String(10))
    work = db.Column(db.String(20))

    def __repr__(self):
        return 'name:{name} work:{work}'.format(name=self.name, work=self.work)

    customer_to_product = db.relationship('Product',
                                          secondary=association_table,
                                          backref='product_to_customer',
                                          lazy='dynamic'
                                          )


class Product(db.Model):
    __tablename__ = 'product'
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    name = db.Column(db.String(10))
    price = db.Column(db.Float)

    def __repr__(self):
        return 'name:{name} price:{price}'.format(name=self.name, price=self.price)


key = '盐'
pro = Product.query.filter_by(name=key).first()
print(pro, type(pro))
c = pro.product_to_customer
print(c, type(c))

for i in c:
    print(i.name, i.work)

输出:

name:盐 price:3.0 <class '__main__.Product'>
[name:程老板 work:大兴有限公司, name:司马老板 work:小马加油有限公司] <class 'sqlalchemy.orm.collections.InstrumentedList'>
程老板 大兴有限公司
司马老板 小马加油有限公司
``


同理,通过查询某个人的信息,找到这个人购买了哪些产品?

```python
key = '司马老板'
ct = Customer.query.filter_by(name=key).first()
print(ct, type(ct))

p = ct.customer_to_product
print(p, type(p))

for i in p:
    print(i.name, i.price)

结果为:

name:司马老板 work:小马加油有限公司 <class '__main__.Customer'>
SELECT product.id AS product_id, product.name AS product_name, product.price AS product_price 
FROM product, association 
WHERE %(param_1)s = association.customer_id AND product.id = association.product_id <class 'sqlalchemy.orm.dynamic.AppenderBaseQuery'>
铝合金 54.0
盐 3.0

分析

association表格的模型类:

association_table = db.Table('association',
                             db.Column('id', db.Integer, primary_key=True, autoincrement=True),
                             db.Column('customer_id', db.Integer, db.ForeignKey('customer.id')),
                             db.Column('product_id', db.Integer, db.ForeignKey('product.id'))
                             )

如上的数据库模型类,比另外两个特殊的地方在于,他是在association表格的基础上,再重新定义2个字段的外键,且重新定义了字段的名称。
flask_sqlalchemy把旧的表格association,定义为新的association_table表格去使用
定义了customer_id的字段,来源于外键customer.id(表名+字段)
定义了product_id的字段,来源于外键product.id(表名+字段)

然后,再分析customer表与product表之间的关系

customer_to_product = db.relationship('Product',
                                      secondary=association_table,
                                      backref='product_to_customer',
                                      lazy='dynamic'
                                        )

这两张表格的主键已经通过association_table表格关联。
db.relationship这个方法,主要是关联2个表格的对象之间的关系
使用backref这个参数,可以理解为是一种虚拟的指向关系,从一个对象指向到另一个对象的中间枢纽。
第一个参数:当前类需要关联的----新类名
第二个参数:secondary,这个是重新定义的关联表
第三个参数:新类名指向当前类名的中间枢纽名
lazy:这个是加载表格的方式

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

steventian72

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值