【问题标题】:Django exclude Items from Queryset from another QuerysetDjango 从另一个查询集中排除查询集中的项目
【发布时间】:2015-01-08 15:38:08
【问题描述】:

我有一个相当复杂的模型设置:

  • 音频文件存储在不同的数据库中。
  • 用户可以选择一个数据库,然后一个随机的音频文件应该是 已选中。
  • 对于每个数据库,都有一个可用的问题列表,其中一个将是 也是随机挑选的。

  • 答案已保存,每次用户访问数据库时,我 必须确保他没有得到相同的组合 (音频文件,问题)他已经回答了。

这是我的代码:

class Database(models.Model):
    name = models.CharField(max_length=200, unique=True)
    questions = models.ManyToManyField(Question)

class AudioData(models.Model):    
    database = models.ForeignKey(Database)

class Question(models.Model):
    ...

# added as a helper class for this problem
class AudioQuestionPair(models.Model):
    audioData = models.ForeignKey(AudioData)
    question = models.ForeignKey(Question)
    database = models.ForeignKey(Database)

class NewAnswer(models.Model):
    user = models.ForeignKey(User)
    question = models.ForeignKey(Question)
    audioData = models.ForeignKey(AudioData)
    timestamp = models.DateField(auto_now_add=True)
    body = models.TextField()

我试图弄清楚,如何(有效且不陷入无限循环)选择可用的音频、问题对。目前我已经到了可以得到答案的地步,其中只包含所需的 ID 和对列表。但我不知道如何从配对中排除答案。

answers = NewAnswer.objects.filter(user=request.user).filter(audioData__database=id).values('audioData_id', 'question_id')

结果

[{'audioData_id': 2, 'question_id': 2}, {'audioData_id': 1, 'question_id': 1}]

并获得所有可用的对

pairs = AudioQuestionPair.objects.filter(database=id).values('audioData_id', 'question_id')

结果

 [{'audioData_id': 1, 'question_id': 1}, {'audioData_id': 2, 'question_id': 1}, {'audioData_id': 5, 'question_id': 1}, {'audioData_id': 6, 'question_id': 1}, {'audioData_id': 7, 'question_id': 1}]

我现在如何在第三步中排除它?

【问题讨论】:

    标签: python django django-queryset


    【解决方案1】:

    编辑:很抱歉没有立即理解您的问题;

    似乎最肮脏的选择是循环遍历每个答案:

    answers = NewAnswer.objects.filter(user=request.user).filter(audioData__database=id).values_list('audioData_id', 'question_id')
    available_pairs = AudioQuestionPair.objects.filter(database=id)
    for a in answers:
        available_pairs = available_pairs.exclude(audioData_id=a[0], question_id=a[1])
    

    还应该可以循环遍历每个 NewAnswer 并构建一个(可能很大的)Q 对象并使用它来执行一个大的 OR 查询,但我不确定这是否会大大提高性能,考虑到QuerySets 在被查看之前不会被评估。

    【讨论】:

    • 不幸的是,这不起作用。它需要保持成对。想象有 3 个音频文件(ID 1,2,3)和 3 个问题(ID 1,2,3),这将创建 9 个可能的解决方案:(1,1),(1,2),(1,3),( 2,1) 等等。将两个 exclude 语句链接在一起,如果 ID 为 1 的 AudioFile 至少回答了一个问题,它将删除 (1,x)
    • 你绝对是对的;我编辑了我对不同方法的答案。
    • 谢谢,我想我是在正确的轨道上。仍然无法正常工作。回答的音频和回答的问题是相同的,显然你必须立即过滤它,在第一行将它添加到链中:.values_list('audiodata_id','question_id')。输出为 [(2, 2), (1, 1)]。现在我有一个元组列表,我将其分成两个列表:lists1, list2 = zip(*answers)。输出是:(2, 1) 和 (2, 1),但是当使用 Q 时,它现在不仅会删除 (2,2) 和 (1,1),还会删除 (2,1) 和 (1,2)。 AudioQuestionPair.objects.filter(database=id).exclude(Q(audioData_id__in=list1) & Q(question_id__in=list2))
    • 再次编辑;希望这会有所帮助。
    • 谢谢,使用循环它正在工作。但是,对于执行 available_pairs.exclude 时的每次迭代,是否会有新的数据库连接/查询,还是只会发生在内存中?
    猜你喜欢
    • 2014-04-11
    • 2018-12-04
    • 1970-01-01
    • 2016-05-09
    • 2017-04-17
    • 2018-10-31
    • 1970-01-01
    • 2013-04-08
    • 1970-01-01
    相关资源
    最近更新 更多