代码之家  ›  专栏  ›  技术社区  ›  Andy Baker

关于q对象和外键的一个难题

  •  4
  • Andy Baker  · 技术社区  · 16 年前

    我有一个这样的模型:

    class Thing(models.Model):
        property1 = models.IntegerField()
        property2 = models.IntegerField()
        property3 = models.IntegerField()
    
    class Subthing(models.Model):
        subproperty = models.IntegerField()
        thing = modelsForeignkey(Thing)
        main = models.BooleanField()
    

    我有一个函数,它传递了一个过滤器列表,其中每个过滤器的格式为“type”:something,“value”:x。此函数需要返回一组结果,并将所有筛选器放在一起:

    final_q = Q()
    for filter in filters:
            q = None
            if filter['type'] =='thing-property1':
                q = Q(property1=filter['value'])
            elif filter['type'] =='thing-property2':
                q = Q(property2=filter['value'])
            elif filter['type'] =='thing-property2':
                q = Q(property3=filter['value'])
            if q:
                final_q = final_q & q
    return Thing.objects.filter(final_q).distinct()
    

    每个子项都有一个布尔属性“main”。每个事物都有一个且只有一个子项,其中main==true。

    现在,我需要添加过滤器,它返回所有具有子目录的内容,其中 main==True subproperty==filter['value']

    我能把这个作为 Q 我正在构造的对象?如果不是怎么办?我在新过滤器之前得到的查询集可能非常大,所以我想要一个不涉及结果循环的方法。

    2 回复  |  直到 10 年前
        1
  •  2
  •   Joe Holloway    16 年前

    如果你在他们与事物的关系中明确地给你的小意思一个“相关的名字”,那就容易理解了。

    class Subthing(models.Model):
        ...
        thing = models.ForeignKey(Thing, related_name='subthings')
        ...
    

    现在,你用 Django join syntax 要构建Q对象:

    Q(subthings__main=True) & Q(subthings__subproperty=filter['value'])
    

    反向关系的默认名称是“subthing-set”,但我发现如果给它一个更好的名称,比如“subthing s”,就更容易理解了。

        2
  •  1
  •   Evgeny    16 年前

    使用(而不是 final_q=Q() 一开始)

    final_q=Q(subthing_set__main=True)
    sub_vals = map(lambda v: v['value'], filters)
    if sub_vals:
        final_q = final_q & Q(subthing_set__subproperty__in=sub_vals)
    

    如果你想要什么,你也可以调整你的循环来构建子值列表,并在循环之后应用它。

    子目录集是自动添加相关字段到对象以访问相关子目录。

    您可以指定其他相关名称,例如

    thing=models.ForeignKey(Thing,related_name='subthings')