reakh
reakh

Reputation: 111

Django initiate form fields with model instance

I thought it looks trivial, and was surprised.

What I have

I have a Django model + form (ModelForm).

My user fills in the form, and on my view I have the usual:

    if request.POST:
        form = myForm(request.POST)
    if request.method == "POST" and form.is_valid():
        result = form.save(commit=False) 

Now I need to heavily manipulate some fields of the form (in the "result" object) and I want to check the forms is_valid() again before saving.

The Problem

I tried to create a new form using the "result" object (that is a ModelForm object) using a dictionary (as suggested here)

result_dictionary = dict((x.name, getattr(result, x.name)) for x in result._meta.fields) 

or

result_dictionary = model_to_dict(result, fields=[field.name for field in result._meta.fields])

plus

testForm = myForm(initial=result_dictionary)

but it doesn't pass is_valid() and does'nt give any errors! The fields are passed OK to the new form...

Any ideas?

Upvotes: 0

Views: 1204

Answers (1)

haeric
haeric

Reputation: 159

Sometimes, looking in the Django source can be really helpful, here's BaseForm.is_valid():

def is_valid(self):
    """
    Returns True if the form has no errors. Otherwise, False. If errors are
    being ignored, returns False.
    """
    return self.is_bound and not bool(self.errors)

So if there are no errors, is_valid() returns false because you haven't bound the form, you haven't given the form anywhere to look for data. Try using the form.data dictionary instead, something like this:

if request.POST:
    form = myModel(request.POST)
if request.method == "POST" and form.is_valid():
    form.data['field1'] = 'Changing this'
    form.data['field2'] = 34

    testform = myModel(data=form.data)

Upvotes: 1

Related Questions