django查询,不包括第二个模型中的条目 [英] django queryset excluding entries in second model

查看:145
本文介绍了django查询,不包括第二个模型中的条目的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

 类Word (model.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 (model.Model):
id = models.AutoField(primary_key = True)
id_student = models.ForeignKey(Student)
id_word = models.ForeignKey(Word)
level = model.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'

其中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 = word_learned'

当WordToWorkOn上的查询器返回结果太少(因为他们已经学到了很好从WordToWorkOn移动到WordLearned并删除),我想找到一个Word添加到它。我不知道一个很好的方法是将其限制在WordLearned中的Word。



所以,一般来说,我想我想在Word的查询中执行某种排序的.exclude(),但是它需要根据WordLearned表中的成员资格排除。有没有办法做到这一点?我找到很多关于加入查询的参考资料,但是找不到一个很好的例子,如何做到这一点(可能只是不知道正确的搜索字词)。



我不想只是在每个Word上使用一个标志来指示学习,工作或没有学习,因为最终这将是一个多用户应用程序,我不想为每个用户添加标志。因此,我认为每个集合的多个表将会更好。



所有建议都将被欣赏。

解决方案

首先,关于风格的几个注释。



不需要在 id_ 。 Django为这些FK创建的底层数据库字段后缀为 _id ,所以你会得到一些类似 id_word_id 在数据库中。如果你只是调用字段'''''''等等,那么它会使你的代码更加清晰。



另外,没有必要指定 id 每个模型中的autofields。它们是自动创建的,您只能在需要调用它们时指定它们。同样,不需要在您的Meta中指定 db_table ,因为这也是自动完成的。



最后,在unicode方法的字段上调用 __ unicode __ 。字符串插值将自动执行,再次将其删除将使您的代码更容易阅读。 (如果你真的想明确地这样做,至少使用 unicode(self.word)表单。)



执行以下操作:

  words_to_work_on = Word.objects.exclude(WordLearned.objects.filter student = user))

在引擎盖下将做一个子查询以获取所有WordLearned对象当前用户并将其从返回的单词列表中排除。



但是,特别是考虑到您将来对多用户应用程序的要求,我认为您应该重组表。你想要的是Word与学生之间的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学生(models.Model):
...名称等$ ...
words = models.ManyToManyField (Word,through ='StudentWord')

class StudentWord(models.Model):
word = models.ForeignKey(Word)
student = models.ForeignKey(Student)
level = models.IntegerField()
learn = models.BooleanField()

现在你可以得到所有的话来学习一个特定的学生:

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


I'm making a little vocabulary-quiz app, and the basic model for a word is this:

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'

The model for words I'm currently quizzing myself on is this:

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" indicates how well I've learned it. The set of words I've already learned has this model:

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'

When a queryset on WordToWorkOn comes back with too few results (because they have been learned well enough to get moved into WordLearned and deleted from WordToWorkOn), I want to find a Word to add to it. The part I don't know a good way to do is to limit it to Words which are not already in WordLearned.

So, generally speaking, I think I want to do an .exclude() of some sort on a queryset of Words, but it needs to exclude based on membership in the WordLearned table. Is there a good way to do this? I find lots of references to joining querysets, but couldn't find a good one on how to do this (probably just don't know the right term to search for).

I don't want to just use a flag on each Word to indicate learned, working on it, or not learned, because eventually this will be a multi-user app and I wouldn't want to have flags for every user. Hence, I thought multiple tables for each set would be better.

All advice is appreciated.

解决方案

Firstly, a couple of notes about style.

There's no need to prefix the foreign key fields with id_. The underlying database field that Django creates for those FKs are suffixed with _id anyway, so you'll get something like id_word_id in the db. It'll make your code much clearer if you just call the fields 'word', 'student', etc.

Also, there's no need to specify the id autofields in each model. They are created automatically, and you should only specify them if you need to call them something else. Similarly, no need to specify db_table in your Meta, as this is also done automatically.

Finally, no need to call __unicode__ on the fields in your unicode method. The string interpolation will do that automatically, and again leaving it out will make your code much easier to read. (If you really want to do it explicitly, at least use the unicode(self.word) form.)

Anyway, on to your actual question. You can't 'join' querysets as such - the normal way to do a cross-model query is to have a foreignkey from one model to the other. You could do this:

words_to_work_on = Word.objects.exclude(WordLearned.objects.filter(student=user))

which under the hood will do a subquery to get all the WordLearned objects for the current user and exclude them from the list of words returned.

However, and especially bearing in mind your future requirement for a multiuser app, I think you should restructure your tables. What you want is a ManyToMany relationship between Word and Student, with an intermediary table capturing the status of a Word for a particular Student. That way you can get rid of the WordToWorkOn and WordLearned tables, which are basically duplicates.

Something like:

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()

Now you can get all the words to learn for a particular student:

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

这篇关于django查询,不包括第二个模型中的条目的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆