Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

Python

Confused about quiz_create's quiz.course line

Hi Teamtreehouse

I just completed the Model Forms module and really enjoyed it. But there as one thing I didn't quite understand.

In quiz_create there is one line I don't quite understand:

@login_required
def quiz_create(request, course_pk): #we use course_pk to know course it belongs to
  course = get_object_or_404(models.Course,pk =course_pk) #here we want to get the course this belongs to first
  form = forms.QuizForm() #here we want to make a blank form first.

  if request.method == 'POST' #someone has posted our form
    form = forms.QuizForm(request.POST) #this is the data the user entered in
    if form.is_valid():
      quiz = form.save(commit=False)
      quiz.course = course
      quiz.save()
      messages.add_message(request, messages.SUCCESS,
                           "Quiz added!")
      return HttpResponseRedirect(quiz.get_absolute_url())
    return render(request, 'courses/quiz_form.html', {'form':form})

I am confused about quiz.course = course. Why do we need this line and where does quiz.course come from?

From what I understand quiz is an instanciation of form, which in turn is an instanciation of the QuizForm, which in itslef is a model form based on Quiz. Quiz in itself is an inhereted model based on Step.

I understand that Step has a course variable, but the model form QuizForm does not include this field when it is generated. Do we still have access to this attribtue even though it hasn't been included as a field in the creation of the model form?

Any advice would be highly appreciated.

Mike

1 Answer

Chris Freeman
MOD
Chris Freeman
Treehouse Moderator 68,468 Points

Hey Mike,

TL;DR: quiz.course = course is needed since it's not asked for in the form so it's not present in the POST data.

The contents of the form is defined in courses/forms.py QuizForm. The fields attribute defines the fields present in the form: ['title', 'description', 'order', 'total_questions',]. What is missing is the inherited course field from Step which is referenced through the instance reference quiz.course. This attribute must be defined before the new quiz instance can be saved. With comments, here are the key lines:

            # create a quiz instance based on Quiz model and the form data, but do Not save, yet
            # this quiz instance will have all fields defined except for 'course'
            quiz = form.save(commit=False)
            # Add the course reference obtained from the URL pk
            quiz.course = course
            # Now, save the quiz instance
            quiz.save()

If the fields attribute was not used in QuizForm, all Quiz fields would have been present in the form. A widget would have been created for the course field. Since course is a ForeignKey field, a model filed to form field substitution is make to include a ModelChoiceField as a dropdown menu of all available courses.

Since we already know which course we are referring to (via the URL), the course dropdown in the form is not necessary.

A very roundabout alternative way to do this same functionality would be to include the courses field in the form as a hidden or read-only field predefined with the know course value, then populate the quiz instance with all the fields present in the posted data. This has the security issue that the course field could be manually manipulated by the user to change the course value to a bogus value before posting.

Post back if you have further questions.

THXVM Chris. Very clear.