SQLALCHEMY表关系
- 一对一
# 添加一对一的反向引用,在一对多的情况下添加uselist=False就变成了一对一
rank_related_score = db.relationship('tbl_2018_data',
backref = 'score_related_rank', uselist=False)
- 一对多
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 表
- 多对多
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:这个是加载表格的方式