ros*_*idh 0 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:
db_table = u'word'
Run Code Online (Sandbox Code Playgroud)
我目前正在自我测验的单词模型是这样的:
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'
Run Code Online (Sandbox Code Playgroud)
"水平"表示我学到了多少.我已经学过的一组单词有这个模型:
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'
Run Code Online (Sandbox Code Playgroud)
当WordToWorkOn上的查询集返回时结果太少(因为它们已经足够好地学习以便移动到WordLearned并从WordToWorkOn中删除),我想找到要添加到其中的Word.我不知道一个好方法的部分是将它限制为尚未在WordLearned中的单词.
所以,一般来说,我想我想在一个单词的查询集上做某种类型的.exclude(),但它需要根据WordLearned表中的成员资格进行排除.有没有办法做到这一点?我发现有很多关于加入查询集的参考资料,但是找不到一个关于如何做到这一点的好文章(可能只是不知道要搜索的正确术语).
我不想只是在每个Word上使用一个标志来表示学习,处理或不学习,因为最终这将是一个多用户应用程序,我不希望每个用户都有标记.因此,我认为每组的多个表会更好.
所有建议表示赞赏.
首先,关于风格的几个注释.
不需要为外键字段添加前缀id_.Django为这些FK创建的底层数据库字段_id无论如何都是后缀,所以你会得到类似于id_word_iddb的东西.如果你只是调用字段'word','student'等,它会让你的代码更清晰.
此外,无需id在每个模型中指定自动对话框.它们是自动创建的,只有在需要调用其他内容时才应指定它们.同样,不需要db_table在Meta中指定,因为这也是自动完成的.
最后,无需调用__unicode__unicode方法中的字段.字符串插值将自动执行,并再次将其删除将使您的代码更容易阅读.(如果你真的想明确地这样做,至少要使用unicode(self.word)表格.)
无论如何,关于你的实际问题.您无法像这样"加入"查询集 - 执行跨模型查询的常规方法是从一个模型到另一个模型使用外键.你可以这样做:
words_to_work_on = Word.objects.exclude(WordLearned.objects.filter(student=user))
Run Code Online (Sandbox Code Playgroud)
引擎盖下将执行子查询以获取当前用户的所有WordLearned对象,并将其从返回的单词列表中排除.
但是,特别是考虑到您对多用户应用程序的未来需求,我认为您应该重新构建表.你想要的是Word和Student之间的ManyToMany关系,中间表捕获特定学生的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()
Run Code Online (Sandbox Code Playgroud)
现在,您可以获得为特定学生学习的所有单词:
words_to_learn = Word.objects.filter(studentword__student=student, studentword__learned=False)
Run Code Online (Sandbox Code Playgroud)