سؤال

أقوم بعمل تطبيق صغير للمفردات ، والنموذج الأساسي لكلمة ما هو:

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'

عندما تعود مجموعة QuerySet على WordToworkon ببعض النتائج (لأنه تم تعلمها جيدًا بما يكفي للانتقال إلى WordleArd وحذفها من WordToworkon) ، أريد أن أجد كلمة لإضافتها. الجزء الذي لا أعرفه عن طريقة جيدة للقيام به هو الحد من الكلمات التي لم يتم بالفعل في Wordlealked.

لذا ، بشكل عام ، أعتقد أنني أريد أن أفعل .exclude () من نوع ما على مجموعة من الكلمات ، ولكن يجب أن تستبعد بناءً على العضوية في الجدول المحدد. هل هناك طريقة جيدة للقيام بذلك؟ أجد الكثير من الإشارات إلى الانضمام إلى QuerySets ، لكن لم أتمكن من العثور على واحدة جيدة حول كيفية القيام بذلك (ربما لا تعرف المصطلح المناسب للبحث عنه).

لا أريد فقط استخدام علامة على كل كلمة للإشارة إلى المستفادة أو العمل عليها أو لم يتم تعلمها ، لأن هذا في النهاية سيكون تطبيقًا متعدد المستخدمين ولا أرغب في الحصول على أعلام لكل مستخدم. وبالتالي ، اعتقدت أن الجداول المتعددة لكل مجموعة ستكون أفضل.

كل النصائح موضع تقدير.

هل كانت مفيدة؟

المحلول

أولاً ، بضع ملاحظات حول الأناقة.

ليست هناك حاجة إلى بادئة حقول المفاتيح الخارجية مع id_. يتم تلميع حقل قاعدة البيانات الأساسي الذي ينشئه Django لتلك FKS _id على أي حال ، لذلك ستحصل على شيء مثل id_word_id في DB. سيجعل الكود الخاص بك أكثر وضوحًا إذا قمت فقط بالاتصال بكلمة الحقول "،" الطالب "، إلخ.

أيضا ، ليست هناك حاجة لتحديد id Autofields في كل نموذج. يتم إنشاؤها تلقائيًا ، ويجب عليك تحديدها فقط إذا كنت بحاجة إلى تسمية شيء آخر. وبالمثل ، لا حاجة لتحديد db_table في التعريف الخاص بك ، حيث يتم ذلك أيضًا تلقائيًا.

أخيرًا ، لا حاجة للاتصال __unicode__ على الحقول في طريقة Unicode الخاصة بك. ستعمل الاستيفاء على السلسلة على ذلك تلقائيًا ، وسيجعل تركه مرة أخرى رمزًا أسهل في القراءة. (إذا كنت تريد حقًا القيام بذلك بشكل صريح ، فاستخدم على الأقل unicode(self.word) شكل.)

على أي حال ، على سؤالك الفعلي. لا يمكنك "الانضمام" على هذا النحو - الطريقة العادية لإجراء الاستعلام عبر النموذج هي أن يكون لديك نظام أجنبي من نموذج إلى آخر. أنت استطاع افعل هذا:

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

التي ستقوم تحت غطاء محرك السيارة بإجراء مساع فرعي للحصول على جميع الكائنات التي تم الحصول عليها للمستخدم الحالي واستبعادها من قائمة الكلمات التي تم إرجاعها.

ومع ذلك ، وخاصة مع الأخذ في الاعتبار متطلباتك المستقبلية لتطبيق متعدد ، أعتقد أنه يجب عليك إعادة هيكلة طاولاتك. ما تريده هو علاقة متعددة بين 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)
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top