代码之家  ›  专栏  ›  技术社区  ›  user2896120

如何在查询集中使用筛选值创建另一列

  •  1
  • user2896120  · 技术社区  · 6 年前

    我有一个查询可以检索20个问题。然后,查询应该向查询集中添加另一列或数据,以指示用户已回答了哪个选项。所以总共有4个模型,包括一个用户模型。

    class Question(models.Model):
        user            = models.ForeignKey(User, on_delete=models.CASCADE)
        status          = models.CharField(max_length=200)
        total_votes     = models.IntegerField(default=0)
    
    class Choice(models.Model):
        question    = models.ForeignKey(Question, on_delete=models.CASCADE)
        choice      = models.CharField(max_length=120)
        vote_count  = models.IntegerField(default=0)
    
    class Voting(models.Model):
        user    = models.ForeignKey(User, on_delete=models.CASCADE)
        choice  = models.ForeignKey(Choice, on_delete=models.CASCADE)
    

    查询

    Question.objects.filter(
            Q(user=3))[:20]
    

    当我这样做时,它不起作用:

    Question.objects.filter(Q(user=1)).annotate(which_answer= filter(choice__question=3, user=1))[:20]
    

    我得到 TypeError: filter() does not take keyword arguments

    如何在此查询中添加另一列以显示用户选择的选项?

    1 回复  |  直到 6 年前
        1
  •  1
  •   bryan60    6 年前

    注释需要如下所示(如果用户ID=1):

    choice_query = Subquery(Choice.objects.filter(question=OuterRef('pk')).values('choice')[:1], output_field=models.CharField())
    
    Question.objects.filter(user=1).annotate(which_answer=choice_query)[:20]
    

    您可以编写一个子查询,该查询根据要注释的问题和用户筛选选择对象,只选择1(假定只选择1),并将该选择值输出到char字段,然后使用该子查询进行注释。

    只是一个旁注:这里的q表达式似乎不需要。

    不确定这里的用例是什么,但是如果您使用序列化程序,只需向主查询添加一个select相关的子句,而不必担心注释,那么您也可能会看到更多的运气或更好的性能。

    编辑:经过讨论,我相信你真正想要的是用户的投票,这是他们的选择。如下所示(同样,用户ID=1):

    vote_query = Subquery(Vote.objects.filter(question=OuterRef('pk'), user=1).values('choice')[:1], output_field=models.IntegerField())
    
    Question.objects.filter(user=1).annotate(which_answer=vote_query)[:20]
    

    此查询将把所选用户选项的ID输出到which_answer注释。