문제

나는 약간의 어휘-퀴즈 앱을 만들고 있으며, 단어의 기본 모델은 다음과 같습니다.

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'

여기서 "레벨"은 내가 얼마나 잘 배웠는지를 나타냅니다. 내가 이미 배운 단어 세트에는이 모델이 있습니다.

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의 쿼리 세트에 결과가 너무 적을 때 (WordLearning으로 이동하고 WordToworkon에서 삭제할 수있을만큼 잘 배웠기 때문에) 추가 할 단어를 찾고 싶습니다. 내가 할 좋은 방법을 모르는 부분은 그것을 아직 단어 학적으로 제한하지 않은 단어로 제한하는 것입니다.

따라서 일반적으로 말하면, 나는 단어의 쿼리 세트에 어떤 종류의 .exclude ()를하고 싶다고 생각하지만 WordLearned 테이블의 멤버십을 기반으로 제외해야합니다. 이것을하는 좋은 방법이 있습니까? 나는 쿼리 세트에 가입하는 것에 대한 많은 언급을 찾았지만, 이것을하는 방법에 대한 좋은 것을 찾을 수 없었습니다 (아마도 검색 할 올바른 용어를 알지 못할 것입니다).

나는 각 단어에 깃발을 사용하여 배운, 작업 또는 배운 것을 나타내는 것을 나타내고 싶지 않습니다. 결국 이것은 다중 사용자 앱이 될 것이며 모든 사용자에게 플래그를 갖고 싶지 않기 때문입니다. 따라서 각 세트에 대한 여러 테이블이 더 좋을 것이라고 생각했습니다.

모든 조언에 감사드립니다.

도움이 되었습니까?

해결책

첫째, 스타일에 대한 몇 가지 메모.

외국 키 필드를 다음과 접두사 할 필요가 없습니다. id_. Django가 FKS를 위해 작성하는 기본 데이터베이스 필드는 다음과 같습니다. _id 어쨌든, 당신은 당신이 같은 것을 얻을 수 있습니다 id_word_id DB에서. 필드 '단어', '학생'등을 호출하면 코드가 훨씬 더 명확 해집니다.

또한 지정할 필요가 없습니다 id 각 모델의 자동 장. 자동으로 생성되며 다른 것을 호출 해야하는 경우에만 지정해야합니다. 마찬가지로 지정할 필요가 없습니다 db_table 메타에서는 자동으로 수행됩니다.

마지막으로 전화 할 필요가 없습니다 __unicode__ 유니 코드 방법의 필드에서. 문자열 보간은 자동으로이를 수행하며 다시 남겨두면 코드를 훨씬 쉽게 읽을 수 있습니다. (정말로 명시 적으로하고 싶다면 적어도 unicode(self.word) 형태.)

어쨌든, 당신의 실제 질문에. 쿼리 세트를 '조인'할 수는 없습니다. 크로스 모델 쿼리를 수행하는 일반적인 방법은 한 모델에서 다른 모델로 외국 키를 갖는 것입니다. 너 ~할 수 있었다 이 작업을 수행:

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

후드 아래에서는 하위 퀘스트를 수행하여 현재 사용자의 모든 WordLearned 객체를 가져 와서 반환 된 단어 목록에서 제외합니다.

그러나 특히 다중 사용자 앱에 대한 미래의 요구 사항을 염두에두고 테이블을 재구성해야한다고 생각합니다. 당신이 원하는 것은 단어와 학생 사이의 많은 사람들의 관계이며, 중개자 테이블은 특정 학생의 단어의 상태를 포착합니다. 이렇게하면 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)
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top