代码之家  ›  专栏  ›  技术社区  ›  HWM-Rocker

如何用q正确过滤many2many/generic关系?

  •  2
  • HWM-Rocker  · 技术社区  · 14 年前

    我有3个模型,TaggedObject与ObjectTagBridge具有泛型关系。而objecttagbridge有一个标签模型的foreignkey。

    class TaggedObject(models.Model):
        """
            class that represent a tagged object
        """
        tags = generic.GenericRelation('ObjectTagBridge',
                                       blank=True, null=True)
    
    class ObjectTagBridge(models.Model):
        """
            Help to connect a generic object to a Tag.
        """
        # pylint: disable-msg=W0232,R0903
        content_type = models.ForeignKey(ContentType)
        object_id = models.PositiveIntegerField()
        content_object = generic.GenericForeignKey('content_type', 'object_id')
        tag = models.ForeignKey('Tag')
    
    class Tag(models.Model):
        ...
    

    当我将一个标记附加到一个对象时,我正在创建一个新的ObjectTagBridge,并将它的ForeignKey标记设置为我要附加的标记。这很好用,我可以很容易地把所有的标签贴到我的物品上。但是,当我想获取(过滤)所有具有tag1和tag2的对象时,我尝试这样做:

    query = Q(tags__tag=Tag1) & Q(tags__tag=Tag2)
    object_list = TaggedObjects.filter(query)
    

    但是现在我的对象列表是空的,因为它正在查找一个带有两个标记对象的ObjectTagBridge,第一个带有Tag1,第二个带有Tag2。

    我的应用程序将比这个更复杂的Q查询,所以我想我需要这个Q对象的解决方案。实际上,任何二元连词的组合,如: (...) and ( (...) or not(...))

    如何正确筛选?每一个答案都是受欢迎的,也许也有不同的方法来实现这一点。

    谢谢你的帮助!!!!

    2 回复  |  直到 6 年前
        1
  •  1
  •   Mathieu Steele    14 年前

    如果您要查找的结果是具有tag1和tag2的taggedObject,请考虑查询taggedObject,而不是查询ObjectTagBridge。这就是该查询的外观:

    results = TaggedObject.objects.filter(objecttagbridge__tag = Tag1).filter(objecttagbridge__tag = Tag2)
    

    从本质上讲,我们正在进行两个滤波器。只有同时具有tag1和tag2的对象才能通过筛选条件并成为结果集的一部分。

        2
  •  0
  •   T. Stone    14 年前

    看起来您正在尝试手动实现一个多对多表,然后将其与一般关系结合起来。更好的方法可能是让Django为您处理M2M,并让它在一般关系中表示,如:

    class TaggedObject(models.Model):
        """
            Help to connect a generic object to a Tag.
        """
        content_type = models.ForeignKey(ContentType)
        object_id = models.PositiveIntegerField()
        content_object = generic.GenericForeignKey('content_type', 'object_id')
        tags = models.ManyToManyField('Tag')
    
    class Tag(models.Model):
        ...
    

    这应该让你做你想做的…

    objects = TaggedObject.objects.filter(
        Q(tags=Tag1) & Q(tags=Tag2)
    )