Skip to main content
 首页 » 编程设计

python之SQLAlchemy一对多关系,如何过滤集合

2024年10月25日32txw1958

基本上 Product 与 ProductPicture 具有一对多的关系。

我的产品图片模型是这样的:

picture_type_enums = ('main', 'related', 'option') 
 
class ProductPicture(Base): 
 
    __tablename__ = 'product_pictures' 
 
    picture_id = Column(Integer, primary_key = True) 
    product_id = Column(Integer, ForeignKey('products.product_id')) 
    picture_type = Column(Enum(*picture_type_enums)) 
    url = Column(String(120)) 

我的产品模型是这样的:

class Product(Base): 
 
    __tablename__ = 'products' 
 
    product_id = Column(Integer, primary_key=True) 
    product_name = Column(String(100)) 
    product_pictures = relationship("ProductPicture") 

我的问题是对于一种产品,我可能有不同类型的产品图片。我知道如果我有一个 Product 实例 p,我可以调用 p.product_pictures 来获取所有类型的产品图片。但是,我想要类似 p.main_pictures 的东西,它获取类型为 'main' 的所有产品图片,而 p.option_pictures 获取所有 product_pictures 类型为 'option'。有什么好的方法吗?

谢谢

请您参考如下方法:

如果您阅读 sqlalchemy.orm.relationship 的文档,您可以看到您可以通过使用 primaryjoin 参数显式定义条件来进一步限制关系,并提供一个完美说明您所需场景的示例。根据您的要求进行调整,Product 类现在如下:

class Product(Base): 
 
    __tablename__ = 'products' 
 
    product_id = Column(Integer, primary_key=True) 
    product_name = Column(String(100)) 
    product_pictures = relationship("ProductPicture") 
 
    main_pictures = relationship("ProductPicture", 
        primaryjoin="and_(Product.product_id==ProductPicture.product_id, " 
                    "ProductPicture.picture_type=='main')") 
    option_pictures = relationship("ProductPicture", 
        primaryjoin="and_(Product.product_id==ProductPicture.product_id, " 
                    "ProductPicture.picture_type=='option')") 

示例 session :

>>> p = Product() 
>>> p.product_name = 'test product' 
>>> p.product_id = 1 
>>> session.add(p) 
>>> pic1 = ProductPicture() 
>>> pic1.product_id = p.product_id 
>>> pic1.picture_type = 'main' 
>>> pic1.url = 'http://example.com/p1.main.png' 
>>> session.add(pic1) 
>>> pic2 = ProductPicture() 
>>> pic2.product_id = p.product_id 
>>> pic2.picture_type = 'option' 
>>> pic2.url = 'http://example.com/p1.option1.png' 
>>> session.add(pic2) 
>>> pic3 = ProductPicture() 
>>> pic3.product_id = p.product_id 
>>> pic3.picture_type = 'option' 
>>> pic3.url = 'http://example.com/p1.option2.png' 
>>> session.add(pic3) 
>>> session.commit() 
>>> [(pic.picture_type, pic.url) for pic in p.product_pictures] 
[(u'main', u'http://example.com/p1.main.png'), (u'option', u'http://example.com/p1.option1.png'), (u'option', u'http://example.com/p1.option2.png')] 
>>> [(pic.picture_type, pic.url) for pic in p.main_pictures] 
[(u'main', u'http://example.com/p1.main.png')] 
>>> [(pic.picture_type, pic.url) for pic in p.option_pictures] 
[(u'option', u'http://example.com/p1.option1.png'), (u'option', u'http://example.com/p1.option2.png')]