Django DB,查找其项目都在子集中的类别

时间:2009-04-02 07:03:47

标签: django django-models

我有两个型号:

class Category(models.Model):
    pass

class Item(models.Model):
    cat = models.ForeignKey(Category)

我正在尝试返回所有类别的项目属于 item ID的给定子集的所有类别(固定谢谢)。例如,与该类别相关联的所有项目的所有类别都在集合[1,3,5]中具有ID。

如何使用Django的查询语法(从1.1 beta开始)?理想情况下,所有工作都应该在数据库中完成。

3 个答案:

答案 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在没有外键的情况下在模型上创建反向关系。您可以使用其相关名称(通常只是模型名称小写但可以手动覆盖),两个下划线以及要查询的字段名称对其进行过滤。