我正在编写一个旨在教授语言的网站。这个想法是通过验证课程,学生正在解锁其他内容(练习,歌曲......)。在形式上,每节课都附有标签。每当学生验证课程时,他们都会验证相关的标记。每个内容都标有与这些标记相对应的先决条件。
在页面上,我想根据用户解锁的标签显示用户可以访问的所有歌曲。如果他们解锁了与歌曲相关的所有标签,他们就可以查看;否则他们不能。
以下是课程模型(称为 cours ):
class Cours(models.Model):
niveau=models.ForeignKey(Niveau,on_delete=models.CASCADE)
titre=models.CharField(max_length=255, unique=True)
tags=models.ManyToManyField(Tag)
这是一首歌的模型:
class Chanson(models.Model):
titre=models.CharField(max_length=255, unique=True)
prerequis=models.ManyToManyField(Tag,blank=True,related_name="+")
以下是用户个人资料的模型以及我发现使用Python built-in sets回答问题的解决方案。
class Profil(models.Model):
user=models.OneToOneField(User, on_delete=models.CASCADE, primary_key=True)
cours_valides=models.ManyToManyField(Cours)
chanson_valides=models.ManyToManyField(Chanson)
def songs_to_do(self):
songlist=Chanson.objects.exclude(id__in=self.chanson_valides.values_list('id',flat=True))
outputsonglist=list()
for song in songlist:
if set(song.prerequis.values_list('id',flat=True))<=set(self.cours_valides.values_list('tags',flat=True)):
outputsonglist.append(song)
return outputsonglist
要执行的歌曲方法基本上会返回用户尚未涵盖的歌曲列表,但可以根据目前为止验证的课程进行访问。实际上, cours valides 字段列出了用户验证的所有课程,而 chansons valides 字段列出了用户已经覆盖的所有歌曲。
我想知道是否有更有效的方法来处理这类问题?
答案 0 :(得分:1)
我会执行2次查询:
获取用户不拥有的所有标签:
locked_tags = Tag.objects.exclude(cours__profil=self)
找到所有带有用户尚未解锁的标签的歌曲:
unlocked_songs = Chanson.objects.exclude(prerequis__in=locked_tags)
您的代码如下所示:
class Profil(models.Model):
user=models.OneToOneField(User, on_delete=models.CASCADE, primary_key=True)
cours_valides=models.ManyToManyField(Cours)
chanson_valides=models.ManyToManyField(Chanson)
def unlocked_songs(self):
locked_tags = Tag.objects.exclude(cours__profil=self)
return Chanson.objects.exclude(prerequis__in=locked_tags)