Gab De Jesus
Gab De Jesus

Reputation: 307

Showing Many-To-Many in different model's form in Django?

Say I have three models, a Professor model, a Course model, and a Review model. The user is allowed to make a Review, which reviews a Professor that teaches a certain Course.

I'm thinking of how to model the many to many relationship of Professor and Course, and how to reference that relationship in Review. My idea so far is to use models.ManyToMany to link Professor and Course.

Models.py (Prof)

class Prof(models.Model):
first_name = models.CharField(max_length = 20, unique = False)
last_name = models.CharField(max_length = 20, unique = False)

    def __str__ (self):
        return self.first_name + " " + self.last_name

class Course(models.Model):
    name = models.CharField(max_length = 20, unique = True)
    prof = models.ManyToManyField(Prof)

    def __str__ (self):
        return self.name

Models.py (Review)

class Review(models.Model):
    message = models.TextField(max_length = 4000)
    created_at = models.DateTimeField(auto_now_add = True)
    updated_at = models.DateTimeField(null = True)
    rating = models.IntegerField(
        default = 5, 
        validators = [MaxValueValidator(5), MinValueValidator(0)]
    )
    prof = models.ForeignKey(Prof, related_name = 'reviews')
    course = models.ForeignKey(Course, related_name = 'reviews')
    user = models.ForeignKey(User, related_name = 'reviews')

    def __str__ (self):
        return self.message   

forms.py

class ReviewForm(ModelForm):
    rating = CharField(widget=TextInput(attrs={'type': 'number','value': 5, 'min': 0, 'max': 5}))

    class Meta:
        model = Review
        fields = ['message', 'rating', 'prof', 'course', 'user']

This is my code so far for displaying the form

<h1>New Review</h1>
<form method="POST">
    {% csrf_token %}
    <p>{{ review_form.message }}</p>
    <p>{{ review_form.rating }}</p>
    <p>{{ review_form.prof }}</p>
    <!-- The prof chosen's courses should be shown here -->
    <button type="submit">Save</button>
</form>

Right now, forms.py shows all the objects under Course, and i'm not sure how to instead show the courses of a professor. Is it possible to filter the form after a prof is chosen from the drop down, to display the courses he/she teacher?

Upvotes: 2

Views: 76

Answers (1)

Withnail
Withnail

Reputation: 3178

It sounds like you're going about this the right way. You haven't mentioned your urls.py structure yet, or views.py but the most straightforward way to do this is to display the courses by professor, taking the professor's id (or slug-field) in as a parameter - either in the URL (v straightforward) or as the output from a form on a previous page (and reload the template with a professor parameter) or in Ajax, depending on your appetite for shiny-new-things.

In your view, when you call the form, you can then do, along the lines from this answer -

form.courses.queryset = Course.objects.filter(professor__in=[professor.id,])

Note that I've put filtered on a list here, which only has one item - it does give you scope to expand, or to use a queryset for more complicated functions later.

Tweak as appropriate if you're using class-based views. :)

Upvotes: 1

Related Questions