0

我正在尝试使用 Django 的 ORM 执行一个复杂的查询,但我似乎找不到一个好的解决方案。也就是说,我有一个 Web 应用程序,用户可以在其中根据视频回答问题。我需要显示至少有一个问题未回答(未回答)的指定用户的所有视频。我还没能用 ORM 弄明白……我知道我可能会为此编写一个 SQL 查询并使用原始 SQL 函数执行它,但我真的更愿意留在 ORM 中。

模型:视频、问题、响应和默认用户。

关系:

  • 问题与视频有多对多的关系
  • Response 对 Question、Video 和 User 都有一个外键

查询需要做什么:

  • 显示指定用户至少有一个视频问题未回答(未回答)的所有视频。

任何帮助都是极好的!我已经为此苦苦挣扎太久了。

编辑:我拥有的模型是(简化的):

class Video(TimeStampedModel):

     title = models.CharField(max_length=200)
     source_id = models.CharField(max_length=20)


class Question(TimeStampedModel):

    DEMOGRAPHIC_QUESTION = 'd'
    QUESTION_TYPES = (
        (VIDEO_QUESTION, 'Video related question'),
        (DEMOGRAPHIC_QUESTION, 'Demographic question'),
    )

    MULTIPLE_CHOICE = 0
    PLAIN_TEXT = 1
    RESPONSE_TYPE = (
        (MULTIPLE_CHOICE, 'Multiple Choice'),
        (PLAIN_TEXT, 'Plain Text')
    )

    type = models.CharField(max_length=1, choices=QUESTION_TYPES)
    videos = models.ManyToManyField(Video, null=True, blank=True)
    title = models.CharField(max_length=500)
    priority = models.IntegerField()

class Response(TimeStampedModel):
     user = models.ForeignKey(User)
     question = models.ForeignKey(Question)
     video = models.ForeignKey(Video, blank=True, null=True)
     choice = models.ForeignKey(Choice, null=True, blank=True,related_name='selected_choice')
     text = models.CharField(max_length=500, blank=True)

// Not relevant but included for clarity
class Choice(TimeStampedModel):
     question = models.ForeignKey(Question)
     text_response = models.CharField(max_length=500)
     image = models.FileField(upload_to=_get_choice_img_path, blank=True)
     value = models.IntegerField(default=0)
     external_id = models.IntegerField(default=0)
4

1 回答 1

0

从您的模型的外观逻辑上判断,我认为接近以下内容应该没问题。

q = Response.objects.select_related().filter(user__name=user).filter(response__choice=None)

videos = Video.objects.filter(id__in=q.extra(where=["{}>=1".format(q.count())]).values('video_id'))

希望你明白我在那里做了什么。第一行基本上尝试对模型对象进行自然连接。第二行使用第一行中生成的查询来获取计数并检查它是否至少为 1,并获取属于该查询的视频。

于 2013-06-22T10:30:46.923 回答