简体   繁体   中英

Django - ManyToMany relationship not unique


So the case is:
I have a Course model with a manytomany relationship to a student 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.

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. 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.

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. 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.

The solution to this is to restructure the model.

  1. Remove the completed boolean field from the module model.

  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:

     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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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