Reputation: 10847
I'm trying to save a ModelForm as I did a thousand times before, but I'm not getting it to work. This is my Test class:
class FooForm(ModelForm):
class Meta:
model = Account
Now I simple get an object and save it:
a = Account.objects.all()[0]
a.save()
This works. Now I want to pass this object to the form and save it:
f = FooForm(instance=a)
f.is_valid()
... gives False. Even no errors are stored:
f.errors
{}
f.non_field_errors()
[]
Saving throws an error then:
f.save()
>>> AttributeError: 'FooForm' object has no attribute 'cleaned_data'
Any ideas?
[UPDATE]
Regarding to second's comment:
f = Form(data={}, instance=a)
f.save()
[....]
ValueError: The Account could not be changed because the data didn't validate.
f.is_valid()
>>> False
f.errors
{'user': [u'This field is required.']}
>>> a.user
<User: demo>
BTW the django documentation says, passing without data is okay, then you pass an instance:
# Create a form to edit an existing Article.
>>> a = Article.objects.get(pk=1)
>>> f = ArticleForm(instance=a)
>>> f.save()
... and could anyone please clarify the downvote? I think it's not such a strange topic.
Upvotes: 0
Views: 2046
Reputation: 239430
Providing an instance to a ModelForm
merely provides default values for the form. The form still expects POST data. You've given it none.
EDIT BASED ON UPDATE:
By passing an empty dataset, you've essentially reset everything to empty. Again, instance
merely provides the default values for the form to display when it's first rendered. It doesn't have any impact on what final values the form will be saved with. That's where data
comes in.
Try:
f = FooForm(data=a.__dict__, instance=a)
f.is_valid()
Upvotes: 1
Reputation: 28637
the form constructor needs a data
argument (typically request.POST
)
update
what are you actually trying to do? if you just want to change your instance in code, you don't need a form at all.
Upvotes: 2
Reputation: 4781
A form without data passed in is never valid, since there is no data, it also has no errors, since django.forms.BaseForm.full_clean
(the method that is responsible for populating cleaned_data
, errors
and non_field_errors
) doesn't actually do anything if there is no data (is_bound
is False
since there's no data
or files
).
So pass in data (a dictionary or dictionary-like-object, such as request.POST
) into the form as first argument, then check is_valid
again.
Upvotes: 1