2

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?

Gab De Jesus
  • 187
  • 1
  • 14
  • It is possible to filter the courses by professor, but not during template generation. You would need to make an AJAX call to the server and return a filtered course set. – Kendas Nov 16 '17 at 12:19

1 Answers1

1

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

Withnail
  • 3,128
  • 2
  • 30
  • 47
  • Thanks for the answer! I'll try and implement this, and get back to you. (Hopefully with an accept this as answer haha) – Gab De Jesus Nov 17 '17 at 04:11