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 Django Forms Model Forms Save a Model Form

Daniel Henderson
Daniel Henderson
6,768 Points

Don't we need to include "from models import DigitalProduct"?

I don't see the model included at the top of the file. It seems like we need that in order to save the DigitalProduct object through the ORM to the database, unless I'm completely missing the point of model forms.

If the model form is also able to do ORM stuff to the database, then I'm a little lost, given the examples.

It must be that, in the video with 'quiz' and 'course', you're doing an object lookup to know what course the quiz belongs to. On 'quiz_edit', though, the quiz already knows what course it belongs to, so no lookup is needed.

So, does the test for if it's a 'POST' (or else a 'GET') request get done after the form is instantiated? It must be, because the default render needs an (unbound?) form object to send to the view.

products/views.py
from django.core.urlresolvers import reverse
from django.http import HttpResponseRedirect
from django.shortcuts import render
from models import DigitalProduct

from . import forms


def product_form(request, prod_pk):
    form = forms.DigitalProductForm()
    if request.method == 'POST':
        prod = DigitalProduct.objects.get(prod_pk)

        form = forms.DigitalProductForm(instance=prod, data=request.POST)

        if form.is_valid():
            form.save()
            return HttpResponseRedirect(reverse("products:create"))
    return render(request, 'products/product_form.html', {'form': form})

1 Answer

Daniel Henderson
Daniel Henderson
6,768 Points

The answer to the title of my post is NO!. It seems like model forms wrap up all the ORM stuff, so I don't need to include the model the form is built to work with. (Please correct me or elaborate on this assumption if it's not accurate)

My solution is to check FIRST if it's a POST request. If it isn't a POST (and the 'if' falls through to the final return render(request, 'products/product_form.html', {'form': form}) line, I instantiate a "blank" DigitalProductForm for that render.

If it IS a POST, I instantiate a DigitalProductForm, with the parameter data=request.POST. I stripped out any mention or use of the DigitalProduct model itself, and the rest of the logic was essentially correct.

I was not able to instantiate a blank form, then re-use it inside the if request.method == 'POST': clause by packing in the data and applying the instance. It probably would work, but I needed to tear down my incorrect assumptions to follow the logic better (so my answer wasn't completely DRY).