Django——在过滤时将多对多对象集视为一个实体
假设我有三个模型——人、食物、风味。
Person 和 Flavor 具有多对多的关系(一个人可以喜欢多种口味)。
Food 和 Flavor 具有多对多的关系(一种食物可以有多种口味)。
对于任何特定的人,我想返回所有具有一组口味的食物,这些口味是该人口味的子集。
例如,
personA.flavor.all() --> [‘辣’、‘甜’、‘苦’]
foodA.flavor.all() --> [‘辣’、‘甜’]
foodB.flavor.all() -->; [‘辣’、‘苦’]
foodC.flavor.all() --> ['bitter', 'greasy']
我想在 Food.objects 上使用 Django 的过滤器,以便它返回包含 foodA 和 foodB 的 QuerySet。
我知道如果我将用户的口味转换为一个集合,并在每个食物的口味列表上调用 issuperset (并将此类食物添加到预定义的列表中),我可以实现类似的结果,但我想知道(并希望)如果有一个更优雅的解决方案涉及 django 模型的过滤函数,它会返回一个 QuerySet 而不是列表。
预先非常感谢您的帮助。
Say I have three models -- Person, Food, Flavor.
Person and Flavor share a many-to-many relationship (a person can like many flavors).
Food and Flavor share a many-to-many relationship (a food can have many flavors).
For any given person, I would like to return all foods that have a set of flavors that is a subset of the person's flavors.
For example,
personA.flavor.all() --> ['spicy', 'sweet', 'bitter']
foodA.flavor.all() --> ['spicy', 'sweet']
foodB.flavor.all() --> ['spicy, 'bitter']
foodC.flavor.all() --> ['bitter', 'greasy']
I'd like to use Django's filter on Food.objects so that it would return a QuerySet containing foodA and foodB.
I understand I can achieve a similar result if I convert the user's flavors into a set, and call issuperset on each of the food's list of flavors (and add such food to a pre-defined list), but I'm wondering (and hoping) if there's a more graceful solution involving django model's filter function, something that will return me a QuerySet instead of a list.
Thank you very much in advance for your help.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我认为仅使用 django orm 无法实现您所追求的目标。它会以某种方式涉及生成 SQL,该 SQL 能够检查一个结果集是否是另一个结果集的超集。如果您可以轮换结果集,这将是可能的(在 sql 中)。 SQL Server 有 PIVOT 和 UNPIVOT 运算符可以执行此操作(其他 DBMS 包可能有类似的运算符),但 django 无法生成此类 SQL。我怀疑任何通用 ORM 都能够做到这一点。
您已经知道的解决方案已经足够优雅了。两个查询足以获取所需的所有数据,然后通用语言可以更轻松地确定集合成员资格。在 SQL 中这样做将是一场噩梦(我认为)。
不过,好问题。我开始编写 SQL 来实现结果,直到我意识到这将比我在没有得到报酬的情况下花费的时间要麻烦得多(而且可能超出了我的理解范围!)。如果有人发布它,那么看到一个纯 sql 解决方案会非常有趣。
I don't think you can achieve what you're after just using the django orm. It'd somehow involve generating SQL which was capable of checking whether a result set is a superset of another result set. This would be possible (in sql) if you could rotate a result set. SQL Server has the PIVOT and UNPIVOT operators which can do this (other DBMS packages probably have similar operators), but django isn't capable of generating such SQL. I doubt any general purpose ORM would be capable of this.
The solution you're already aware of is quite elegant enough already. Two queries are enough to get all the data required, and then a general purpose language can much more easily determine set membership. Doing so in SQL would be a bit of a nightmare (I think).
Good question though. I started writing out SQL to achieve the result until I realised it was going to be a lot more trouble than I have time for without getting paid (and probably way out of my depth!). It'd be very interesting to see a pure sql solution if anyone posts it though.