Frage

Ich mache eine kleine Vokabular-Quiz-App, und das Grundmodell für ein Wort ist Folgendes:

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'

Das Modell für Wörter, auf denen ich mich gerade befragte, ist Folgendes:

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'

Wo "Level" angibt, wie gut ich es gelernt habe. Der Satz von Wörtern, die ich bereits gelernt habe, hat dieses Modell:

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'

Wenn ein Queryset auf WordToworkon mit zu wenigen Ergebnissen zurückkommt (weil sie gut genug gelernt wurden, um in WordLearned und aus WordToworkon gelöscht zu werden), möchte ich ein Wort finden, um es hinzuzufügen. Der Teil, den ich keinen guten Weg kenne, ist es, es auf Wörter zu beschränken, die noch nicht in WordLearned sind.

Im Allgemeinen denke ich, dass ich eine Art von Worten ausschließt () ausschließt, aber es muss basierend auf der Mitgliedschaft in der WordLearned -Tabelle ausgeschlossen werden. Gibt es einen guten Weg, dies zu tun? Ich finde viele Verweise auf den Beitritt zu QuerySets, konnte aber keinen guten finden, wie man dies macht (wahrscheinlich kenne ich den richtigen Begriff, nach dem ich suchen muss).

Ich möchte nicht nur eine Flagge für jedes Wort verwenden, um gelernt zu werden, daran zu arbeiten oder nicht gelernt zu werden, da dies irgendwann eine Multi-User-App sein wird und ich nicht für jeden Benutzer Flags haben möchte. Daher dachte ich, mehrere Tabellen für jeden Satz wären besser.

Alle Ratschläge werden geschätzt.

War es hilfreich?

Lösung

Erstens ein paar Notizen über Stil.

Es ist nicht erforderlich, die fremden Schlüsselfelder mit dem Voraus zu bringen id_. Das zugrunde liegende Datenbankfeld, das Django für die FKs erstellt hat _id Wie auch immer, also wirst du so etwas wie bekommen id_word_id in der db. Es wird Ihren Code viel klarer, wenn Sie nur die Felder 'Wort', 'Student' usw. anrufen.

Außerdem müssen die nicht angegeben werden id Autofields in jedem Modell. Sie werden automatisch erstellt und Sie sollten sie nur angeben, wenn Sie sie etwas anderes nennen müssen. In ähnlicher Weise müssen Sie nicht angeben db_table In Ihrem Meta, da dies auch automatisch erfolgt.

Schließlich müssen Sie nicht anrufen __unicode__ Auf den Feldern in Ihrer Unicode -Methode. Die String -Interpolation wird dies automatisch erledigen, und es wird Ihr Code erneut leichter zu lesen. (Wenn Sie es wirklich explizit tun möchten, verwenden Sie zumindest die unicode(self.word) bilden.)

Wie auch immer, weiter zu Ihrer tatsächlichen Frage. Sie können QuerySets nicht als solche mitmachen - die normale Möglichkeit, eine Quermodell -Abfrage durchzuführen, besteht darin, einen Fremdkey von einem Modell zum anderen zu haben. Du könnte mach das:

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

Was unter der Motorhaube eine Unterabfrage ausführt, um alle WordLearned -Objekte für den aktuellen Benutzer zu erhalten und sie aus der Liste der zurückgegebenen Wörter auszuschließen.

Und insbesondere wenn Sie Ihre zukünftige Anforderung für eine Multiuser -App berücksichtigen, sollten Sie Ihre Tische umstrukturieren. Was Sie wollen, ist eine Manytomany -Beziehung zwischen Wort und Schüler, wobei eine Vermittlertabelle den Status eines Wortes für einen bestimmten Schüler erfasst. Auf diese Weise können Sie die Worttoworkon- und WordLeared -Tabellen, die im Grunde genommen Duplikate sind, loswerden.

Etwas wie:

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

Jetzt können Sie alle Wörter für einen bestimmten Schüler lernen:

words_to_learn = Word.objects.filter(studentword__student=student, studentword__learned=False)
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top