如何使用 Q 正确过滤 Many2Many / Generic 关系?

发布于 2024-08-30 16:08:26 字数 1243 浏览 8 评论 0原文

我有 3 个模型,TaggedObject 与 ObjectTagBridge 有 GenericRelation。 ObjectTagBridge 有一个标签模型的外键。

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 并将其外键标签设置为我要附加的标签。这工作正常,我可以非常轻松地获取附加到对象的所有标签。但是,当我想获取(过滤)具有 Tag1 和 Tag2 的所有对象时,我尝试这样做:

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

但现在我的 object_list 为空,因为它正在寻找具有一个带有 2 个标签对象的 ObjectTagBridge 的 TaggedObject,第一个带有 Tag1 和第二个带有 Tag2。

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

我怎样才能正确过滤这个?欢迎每个答案,也许还有其他方法可以实现这一目标。

谢谢你的帮助!

I have 3 Models, the TaggedObject has a GenericRelation with the ObjectTagBridge. And the ObjectTagBridge has a ForeignKey to the Tag Model.

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):
    ...

when I am attaching a Tag to an Object, I am creating a new ObjectTagBridge and set its ForeignKey tag to the Tag I want to attach. That is working fine, and I can get all Tags that I attached to my Object very easy. But when I want to get (filter) all Objects that have Tag1 and Tag2 I tried to something like this:

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

but now my object_list is empty, because it is looking for TaggedObjects that have one ObjectTagBridge with 2 tag objects, the first with Tag1 and the second with Tag2.

I my application will be more complex Q queries than this one, so I think I need a solution with this Q object. In fact any combination of binary conjunctions, like: (...) and ( (...) or not(...))

How can I filter this correctly? Every answer is welcome, maybe there is also a different way do achieve this.

thx for your help!!!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

请别遗忘我 2024-09-06 16:08:26

如果您要查找的结果是具有 Tag1 和 Tag2 的 TaggedObject,请考虑查询 TaggedObject 而不是查询 ObjectTagBridge。该查询可能如下所示:

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

本质上我们正在执行两个过滤器。只有同时具有 Tag1 和 Tag2 的对象才会通过过滤条件并成为结果集的一部分。

If the result you are looking for is a TaggedObject with Tag1 and Tag2, consider querying the TaggedObject instead of querying the ObjectTagBridge. This is what that query might look like:

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

Essentially we are conducting two filters. Only objects with both Tag1 and Tag2 will pass the filtering criteria and be a part of the result set.

乖乖 2024-09-06 16:08:26

看起来您正在尝试手动实现多对多表,然后将其与通用关系结合起来。更好的方法可能是让 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)
)

It looks like you are trying to manually implement a Many-to-Many table and then combine that with a generic relation. A better approach might be to let Django handle the M2M for you, and just have it represented on the generic relationship like so:

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):
    ...

This should let you do what you were trying to do...

objects = TaggedObject.objects.filter(
    Q(tags=Tag1) & Q(tags=Tag2)
)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文