Challenge 2: Customize form_valid() — Possible Solution ==================================================================== # catalog/models.py from django.db import models from django.contrib.auth.models import User class Review(models.Model): book = models.ForeignKey("Book", on_delete=models.CASCADE, related_name="reviews") reviewer = models.ForeignKey(User, on_delete=models.CASCADE) text = models.TextField() rating = models.IntegerField() # catalog/views.py from django.contrib.auth.mixins import LoginRequiredMixin from django.views.generic.edit import CreateView from django.urls import reverse_lazy from .models import Review class ReviewCreateView(LoginRequiredMixin, CreateView): model = Review fields = ["book", "text", "rating"] # note: "reviewer" is NOT in this list template_name = "catalog/review_form.html" success_url = reverse_lazy("book-list") def form_valid(self, form): form.instance.reviewer = self.request.user return super().form_valid(form) WHY THIS WORKS -------------- - fields deliberately excludes "reviewer" — the same mass-assignment allowlist principle from Course 1's Forms chapter applies to generic views too. Since reviewer isn't in fields, there's no form input for it at all, meaning no submitted data could ever set it, whether through the rendered form or a crafted request. - form_valid(self, form) is called by CreateView's parent classes only AFTER the submitted data has already passed validation — form.instance at this point is the (not-yet-saved) Review instance built from the valid form data, so setting form.instance.reviewer = self.request.user here attaches the correct user before the object is actually persisted. - return super().form_valid(form) is essential — it's what actually calls form.save() and returns the HttpResponseRedirect to success_url. Overriding form_valid() without calling the parent's implementation (via super()) would mean the Review is never actually saved and the user never gets redirected, since all of that logic lives in ModelFormMixin.form_valid(), not in CreateView.form_valid() itself. - LoginRequiredMixin ensures self.request.user is always a real, authenticated user by the time form_valid() runs — without it, an anonymous request reaching this view would set reviewer to AnonymousUser, which isn't a valid User instance and would fail at save time with a much more confusing error.