简体   繁体   中英

ManyToMany Relationship between two models in Django

I am trying to build a website that users can add the courses they are taking. I want to know how should I add the ManyToMany relationship. Such that we can get all users in a course based on the course code or instructor or any field. And we can also get the courses user is enrolled in. Currently, my Database structure is:

class Course(models.Model):
    course_code = models.CharField(max_length=20)
    course_university = models.CharField(max_length=100)
    course_instructor = models.CharField(max_length=100)
    course_year = models.IntegerField(('year'), validators=[MinValueValidator(1984), max_value_current_year])

    def __str__(self):
        return self.course_code

and my user model:

class Profile(AbstractUser):
    bio = models.TextField()
    image = models.ImageField(default='defaults/user/default_u_i.png', 
    courses = models.ManyToManyField('home.Course',related_name='courses')

    def __str__(self):
        return self.username

I was wondering should ManyToMany relationship be in User model or the course model? Or will it make any difference at all?

EDIT : For adding course to post object now I am using this view but it seems to not work:

@login_required
def course_add(request):

    if request.method == "POST":
        form = CourseForm(request.POST or none)
        if form.is_valid():
            course = form.save()
            request.user.add(course)
    else:
        form = CourseForm
    context = {
        'form':form
    }
    return render(request,'home/courses/course_add.html', context)

For a relational databases, the model where you define the ManyToManyField does not matter. Django will create an extra table with two ForeignKey s to the two models that are linked by the ManyToManyField .

The related managers that are added, etc. is all Django logic. Behind the curtains, it will query the table in the middle.

You however need to fix the related_name=… parameter [Django-doc] . The related_name specifies the name of the relation in reverse so from Course to Profile in this case. It thus should be something like 'profiles' :

class Profile(AbstractUser):
    bio = models.TextField()
    image = models.ImageField(default='defaults/user/default_u_i.png', 
    courses = models.ManyToManyField('home.Course')

    def __str__(self):
        return self.username

You thus can obtain the people that particiate in a Course object with:

mycourse

and you can access the courses in which a Profile is enrolled with:

myprofile

For more information, see the Many-to-many relationships section of the documentation .

You can add a course to the courses of a user with:

@login_required
def course_add(request):
    if request.method == 'POST':
        form = CourseForm(request.POST)
        if form.is_valid():
            course = form.save()
            request.user
    else:
        form = CourseForm()
    context = {
        'form': form
    }
    return render(request,'home/courses/course_add.html', context)

You don't need to add the related name. Default is "courses_set" in your case. Here is excerpt from: https://docs.djangoproject.com/en/dev/topics/db/queries/#backwards-related-objects

Following relationships “backward” If a model has a ForeignKey, instances of the foreign-key model will have access to a Manager that returns all instances of the first model. By default, this Manager is named FOO_set, where FOO is the source model name, lowercased. This Manager returns QuerySets, which can be filtered and manipulated as described in the “Retrieving objects” section above.

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