简体   繁体   English

Django - 多对多关系不是唯一的

[英]Django - ManyToMany relationship not unique


So the case is:所以情况是:
I have a Course model with a manytomany relationship to a student model.我有一门课程 model 与学生 model 有多对多关系。 The course also have a one to many relationship with a Module model, so a course have many modules but each module belongs to one course.该课程还与一个模块 model 具有一对多的关系,因此一个课程有许多模块,但每个模块属于一个课程。

On my Module i specified a boolean field named completed to be able to calculate how much modules of that course did the student complete.在我的模块上,我指定了一个名为完成的 boolean 字段,以便能够计算学生完成了该课程的多少模块。 The main problem is: When a module is completed by a student, it's marked as completed forever.主要问题是:当学生完成一个模块时,它被标记为永远完成。 In other words, when another user enrolls in the same course, he will find the completetion state of the modules as left by the other user.换句话说,当另一个用户注册相同的课程时,他会发现另一个用户留下的模块的完成state。

I want each modules to be initialized when a student enrolls in a course, but also want to them to be saved just for that student without saving the changes globally, it's like making an initialized copy of the course whenever a new user enrolls in it, and save his records on this copy not on the actual Course model in the database.我希望在学生注册课程时初始化每个模块,但也希望仅为该学生保存它们而不全局保存更改,这就像每当新用户注册时制作课程的初始化副本一样,并将他的记录保存在此副本上,而不是数据库中的实际课程 model 上。 Thanks and here's the code:谢谢,这是代码:

class Student(models.Model):
    user        = models.OneToOneField(User, on_delete=models.CASCADE, null=True, blank=True)
    full_name   = models.CharField(max_length=200, null=True, blank=True)
    age         = models.PositiveIntegerField(null=True, blank=True)
    email       = models.CharField(max_length=200, null=True, blank=True)
    phone       = models.CharField(max_length=20, null=True, blank=True)
    about       = models.TextField(null=True, blank=True)
    date_joined = models.DateTimeField(auto_now_add=False, null=True, blank=True)


class Course(models.Model):
    owner = models.ForeignKey(User, related_name='courses_created',help_text=_('owner') ,on_delete=models.CASCADE)
    subject = models.ForeignKey(Subject, related_name='courses',help_text=_('subject') ,on_delete=models.CASCADE)
    title = models.CharField(max_length=200,help_text=_('title'))
    slug = models.SlugField(max_length=200, help_text=_('slug') ,unique=True, allow_unicode=True)
    overview = models.TextField(help_text=_('overview'))
    created = models.DateTimeField(auto_now_add=True)
    thumbnail = models.ImageField(upload_to='images', null=True, blank=True)
    students = models.ManyToManyField(Student, related_name='courses_joined',help_text=_('students'), blank=True)

    def completion_rate(self):
        sum = 0
        for m in self.modules.all():
            if m.completed:
                sum +=1
        rate = int((sum / self.modules.count()) * 100)
        return rate


 class Module(models.Model):
    course = models.ForeignKey(Course, related_name='modules',help_text=_('course') ,on_delete=models.CASCADE)
    title = models.CharField(max_length=200 )
    description = models.TextField(blank=True)
    order = OrderField(blank=True, for_fields=['course'])
    completed = models.BooleanField(default=False, null=True)

and the view that completes a module:以及完成模块的视图:

def complete(request, m_id, c_id):
    mod = get_object_or_404(Module, id=m_id)
    course = get_object_or_404(Course, id=c_id)
    mod.completed = True
    mod.save()
    return redirect('student_course_detail_module', course.id ,mod.id)

This is a logic problem.这是一个逻辑问题。 You are adding a boolean field to the module which once set by a single student will remain set for all other students logging in.您正在向模块添加一个 boolean 字段,一旦由单个学生设置,所有其他登录的学生将保持设置。

The solution to this is to restructure the model.解决此问题的方法是重组 model。

  1. Remove the completed boolean field from the module model.从模块 model 中删除完整的 boolean 字段。

  2. Create another model completed_modules which will have a one-to-one field with student, one-to-one field with course, and a one-to-one field with module as such:创建另一个 model completed_modules 将具有与学生的一对一字段、与课程的一对一字段以及与模块的一对一字段,如下所示:

     class CompletedModules(models.Model): module = models. ForeignKey(Module, on_delete=models.CASCADE) course = models.ForeignKey(Course, on_delete=models.CASCADE) user = models.ForeignKey(Student, on_delete=models.CASCADE)

When a given student completes a given module for a given course, you simply records that in this table当给定学生完成给定课程的给定模块时,您只需将其记录在此表中

You will need to rewrite your completed function to effect this insert operation您需要重写已完成的 function 以实现此插入操作

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM