tags:

views:

147

answers:

2
class JobForm(forms.ModelForm):
    class Meta:
        model = models.Job

That was my form, now trying to save it will raise an exception, and trying to validate it just fails with no errors....

job = get_object_or_404(models.Job, pk=1)
form = forms.JobForm(instance = job)
try:
    form.save()
except:
    print sys.exc_info()

#=>(<type 'exceptions.AttributeError'>, AttributeError("'JobForm' object has no attribute 'cleaned_data'",), <traceback object at 0x1029dbb48>)

Tried to validate it:

if form.is_valid():
    form.save()
else:
    print 'error'
    print form.errors, len(form.errors)
#=> 'error' 
#=> 0

So the form isn't valid, but the there are no errors! Any idea?

+2  A: 

My best guess is that you can't save a model form that has only been created with instance data (I just tried doing this with one of my forms and got the exact same error) because a form doesn't become a bound form until you pass in extra information. It doesn't really make sense to only provide data that already exists on the model to a form (and then save it again) as there wouldn't be any change. If this is coming from an html form, you should also be passing in request.POST (or request.GET) to the form.

Adam
The documentation has an example that just retrieves the model and pass to the form and then saves the form http://docs.djangoproject.com/en/1.1/topics/forms/modelforms/#the-save-method , specifically after this comment # Create a form to edit an existing Article. Anyway I tried what you suggested by doing job.state = 'RUNNING', then passed it to the form but the same error happened. I'm using urllib2 to send that POST request anyway.
khelll
I'm not sure why they provide that as an example (at least saving it), because it doesn't seem possible. To save the form, you'll need to provide the POST dictionary as the first parameter. In order to save the form, is_bound and is_valid() should both return True.
Adam
+2  A: 

Your form is definitely not bound. Read about Bound and Unbound forms.

From that documentation:

To bind data to a form, pass the data as a dictionary as the first parameter to your Form class constructor.

That means that also the change of a field in your model doesn't make the form bound. You have to pass those values explicitly via the constructor. But:

Note that passing an empty dictionary creates a bound form with empty data

and consider this

If you have a bound Form instance and want to change the data somehow, or if you want to bind an unbound Form instance to some data, create another Form instance. There is no way to change data in a Form instance. Once a Form instance has been created, you should consider its data immutable, whether it has data or not.

If you validate an unbound form:

It's meaningless to validate a form with no data, but, for the record, here's what happens with unbound forms:

>>> f = ContactForm()
>>> f.is_valid()
False
>>> f.errors
{}

Felix Kling