我有两个型号:
class Category(models.Model):
pass
class Item(models.Model):
cat = models.ForeignKey(Category)
我正在尝试返回所有类别的项目属于 item ID的给定子集的所有类别(固定谢谢)。例如,与该类别相关联的所有项目的所有类别都在集合[1,3,5]中具有ID。
如何使用Django的查询语法(从1.1 beta开始)?理想情况下,所有工作都应该在数据库中完成。
答案 0 :(得分:0)
假设您要求所有项目都在以下集合中:
allowable_items = set([1,3,4])
一个强力解决方案是检查每个类别的item_set,如下所示:
categories_with_allowable_items = [
category for category in
Category.objects.all() if
set([item.id for item in category.item_set.all()]) <= allowable_items
]
但我们实际上不必检查所有类别,因为categories_with_allowable_items总是与allowable_items中所有具有ID的项目相关的类别的子集...所以我们必须检查(这应该是更快):
categories_with_allowable_items = set([
item.category for item in
Item.objects.select_related('category').filter(pk__in=allowable_items) if
set([siblingitem.id for siblingitem in item.category.item_set.all()]) <= allowable_items
])
如果表现不是真正的问题,那么后两者(如果不是前者)应该没问题。如果这些是非常大的表,您可能需要提出更复杂的解决方案。如果您使用的是特别旧版本的python,请记住您必须导入集合模块
答案 1 :(得分:0)
我已经玩过这个了。如果QuerySet.extra()接受了“having”参数,我认为可以在ORM中使用HAVING子句中的一些原始SQL来完成它。但事实并非如此,所以如果您希望数据库完成工作,我认为您必须在原始SQL中编写整个查询。
修改强>
这是让你在那里的一部分:
from django.db.models import Count
Category.objects.annotate(num_items=Count('item')).filter(num_items=...)
问题是,为了使查询起作用,“...”需要是一个相关的子查询,它为每个类别查找allowed_items中项目的数量。如果.extra有一个“有”参数,你可以这样做:
Category.objects.annotate(num_items=Count('item')).extra(having="num_items=(SELECT COUNT(*) FROM app_item WHERE app_item.id in % AND app_item.cat_id = app_category.id)", having_params=[allowed_item_ids])
答案 2 :(得分:0)
Category.objects.filter(item__id__in=[1, 3, 5])
Django在没有外键的情况下在模型上创建反向关系。您可以使用其相关名称(通常只是模型名称小写但可以手动覆盖),两个下划线以及要查询的字段名称对其进行过滤。