django queryset排除第二个模型中的条目

django queryset排除第二个模型中的条目,django,django-models,django-queryset,Django,Django Models,Django Queryset,我正在制作一个小的词汇测验应用程序,单词的基本模型是: class Word(models.Model): id = models.AutoField(primary_key=True) word = models.CharField(max_length=80) id_image = models.ForeignKey(Image) def __unicode__(self): return self.word class Meta:

我正在制作一个小的词汇测验应用程序,单词的基本模型是:

class Word(models.Model):
    id = models.AutoField(primary_key=True)
    word = models.CharField(max_length=80)
    id_image = models.ForeignKey(Image)
    def __unicode__(self):
        return self.word
    class Meta:
        db_table = u'word'
我目前自考的单词模型是:

class WordToWorkOn(models.Model):
    id = models.AutoField(primary_key=True)
    id_student = models.ForeignKey(Student)
    id_word = models.ForeignKey(Word)
    level = models.IntegerField()
    def __unicode__(self):
        return u'%s %s' % (self.id_word.__unicode__(), self.id_student.__unicode__() )
    class Meta:
        db_table = u'word_to_work_on'
Where level表示我的学习程度。我已经学过的一组单词有这样的模式:

class WordLearned(models.Model):
    id = models.AutoField(primary_key=True)
    id_word = models.ForeignKey(Word, related_name='word_to_learn')
    id_student = models.ForeignKey(Student, related_name='student_learning_word')
    def __unicode__(self):
        return u'%s %s' % (self.id_word.__unicode__(), self.id_student.__unicode__() )
    class Meta:
        db_table = u'word_learned'
当WordToWorkOn上的查询集返回时,结果太少,因为它们已经学习得足够好,可以移动到WordToWorkOn并从WordToWorkOn中删除,我想找到一个要添加到其中的单词。我不知道一个好方法是把它限制在WordLearned中还没有的单词上

所以,一般来说,我想对一组单词的查询集进行某种.exclude,但它需要基于WordLearned表中的成员身份进行排除。有什么好办法吗?我找到了很多关于加入querysets的参考资料,但是找不到一个好的关于如何做到这一点的参考资料,可能只是不知道应该搜索哪个词

我不想在每个单词上都使用一个标志来表示已学习、正在学习或未学习,因为最终这将是一个多用户应用程序,我不希望每个用户都有标志。因此,我认为每套多张桌子会更好


非常感谢您的建议。

首先,请注意一些关于风格的注意事项

不需要在外键字段的前面加上id\前缀。Django为这些FK创建的底层数据库字段的后缀是_id,因此在db中会得到类似于id_word_id的内容。如果只调用字段“word”、“student”等,代码会更清晰

此外,无需在每个模型中指定id自动字段。它们是自动创建的,只有在需要调用其他名称时才应该指定它们。类似地,不需要在元中指定db_表,因为这也是自动完成的

最后,无需对unicode方法中的字段调用_unicode。字符串插值将自动完成这项工作,再次省略它将使代码更易于阅读。如果您确实想显式地执行此操作,至少使用unicodeself.word表单

不管怎么说,请继续回答你的实际问题。您不能像这样“连接”查询集-执行跨模型查询的正常方法是将foreignkey从一个模型连接到另一个模型。您可以这样做:

它将执行一个子查询,以获取当前用户的所有WordLearned对象,并将其从返回的单词列表中排除

然而,特别是考虑到您未来对多用户应用程序的需求,我认为您应该重新构造表。您想要的是Word和Student之间的多个关系,中间表捕获特定学生的Word状态。这样,您就可以摆脱WordToWorkOn和WordLearned表,它们基本上是重复的

比如:

class Word(models.Model):
    word = models.CharField(max_length=80)
    image = models.ForeignKey(Image)
    def __unicode__(self):
        return self.word

class Student(models.Model):
     ... name, etc ...
     words = models.ManyToManyField(Word, through='StudentWord')

class StudentWord(models.Model):
    word = models.ForeignKey(Word)
    student = models.ForeignKey(Student)
    level = models.IntegerField()
    learned = models.BooleanField()
现在,您可以为特定学生学习所有单词:

words_to_learn = Word.objects.filter(studentword__student=student, studentword__learned=False)

哇,三课合一。我将相应地修改我的数据结构,一旦我实际实现了这个答案,我就会回来检查它是否正确,这并不是说我真的怀疑它,只是出于原则。感谢所有的帮助。很好的解决方案,但是你怎么不能接受Word对象,StudentWord表中没有什么?这里还有排除函数中的一些错误,所以不可能使用它按2个或更多字段进行过滤。
words_to_learn = Word.objects.filter(studentword__student=student, studentword__learned=False)