所有
我正在尝试使用Peewee查询用户和地址系统。我试图过滤掉多对多的关系。我找回了正确的对象,但是当我通过list(query)返回对象时,我没有删除不匹配的关系。例如,如果我想获取纽约(纽约州)状态为4的用户的所有地址,我会按原样执行查询:
设定:
class Address(Model):
address_line_1 = CharField(null=True)
address_line_2 = CharField(null=True)
city = CharField(null=True)
state_abbr = CharField(null=True, max_length=2)
state = IntegerField(default=NEW_ID, choices=STATE_CHOICES)
class LicenseNumber(Model):
number = CharField(unique=True, index=True)
state = IntegerField(default=NEW_ID, choices=STATE_CHOICES)
class User(Model):
license = ForeignKeyField(LicenseNumber, null=True)
addresses = ManyToManyField(Address, related_name="users")
state = IntegerField(default=NEW_ID, choices=STATE_CHOICES)
示例:
def get_filtered_users(...):
# Get the through model for the many-to-many relationship
UserAddresses = User.addresses.get_through_model()
# Query users & license & addresses
query = (User
.select(User, Address, LicenseNumber)
.join(UserAddresses)
.join(Address)
.switch(User) # Switch the context back to the user
.join(LicenseNumber)
.where( # Filter out addresses that are not in NY & not state 4
(User.state == 4) &
(Address.state_abbr << ['NY']) &
(Address.state == 4))
.having( # Also tried to ensure that I only get what we want
(Address.state == 4) &
(Address.state_abbr << ['NY'])))
# Return the users
return list(query)
当我查看对象视图query.dict()时,我可以查看返回的项目,它们是正确的。有没有办法返回具有过滤关联关系的实例化User对象?查看过滤后的记录时,我希望在执行查询时看到过滤掉的关系。
用户1:
地址1
用户1:
地址1
地址2:
目标是使用User对象并引用通过以下方式过滤的地址:
# Return the users & their filtered information
return list(query)
在迭代记录实例时,我是否遗漏了过滤掉关系中记录的内容?任何帮助都会很棒
答案 0 :(得分:1)
这让我花了一些时间来仔细搜索和阅读文档。
解决方案是使用PeeWee提供的aggregate_rows功能。此功能有助于防止N + 1查询(您需要获取相关记录)。
本质上,这将选择SELECT语句中定义的关系。因为我们在查找地址状态时正在进行多对多关系,所以我们需要涉及三个表。在这种情况下,它将是select语句中的Users,UserAddresses(直通表)和Addresses all。最后,我们需要调用aggregate_rows()来执行提取和组合。
代码应如下所示:
def get_filtered_users(...):
# Get the through model for the many-to-many relationship
UserAddresses = User.addresses.get_through_model()
# Query users & license & addresses
query = (User
.select(User, Address, UserAddresses, LicenseNumber)
.join(UserAddresses)
.join(Address)
.switch(User) # Switch the context back to the user
.join(LicenseNumber)
.where( # Filter out addresses that are not in NY & not state 4
(User.state == 4) &
(Address.state_abbr << ['NY']) &
(Address.state == 4))
.aggregate_rows())
# Return the users
return list(query)
我们现在收到了州的预期结果:4