SQLALCHEMY表关系

  1. 一对一
# 添加一对一的反向引用,在一对多的情况下添加uselist=False就变成了一对一
    rank_related_score = db.relationship('tbl_2018_data', 
    backref = 'score_related_rank', uselist=False)
  1. 一对多
    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
如上的数据库模型类,比另外两个特殊的地方在于,他是在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:这个是加载表格的方式