Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does Django ModelForm set unspecified fields to empty?

I have a Model that looks like:

class MyModel(Model):
  name = models.TextField(blank=True, default='')
  bio = models.TextField(blank=True, default='')

and a ModelForm that looks like:

class MyModelForm(ModelForm):

  class Meta:
      model = MyModel
      fields = ('name', 'bio')

When I create/ init my form like this:

form = MyModelForm(instance=my_model, data={'bio': 'this is me'})  # where my_model has a name already set

then:

form.is_valid() # evaluates to true
form.save() # overwrites the name field in my_model and makes it blank!

Is this the expected behaviour? How would I change this so that I can ensure that if a field is not specified in the form, but it exists already in the instance that it is not overwritten with an empty string?

like image 291
9-bits Avatar asked Sep 06 '26 04:09

9-bits


2 Answers

Note that Django only sets the name field to empty because you have set blank=True. If the field was required, there would be a validation error instead.

Recently there was a discussion on the django-developers group about changing this behaviour. The core developers Adrian and Paul were in favour of the current behaviour.

So, if you're going to use model forms for this view with models where you use blank=True, you'll need to include all the model fields in your data dict. You can use the function model_to_dict for this.

from django.forms.models import model_to_dict
data = model_to_dict(my_model)
data.update({'bio': 'this is me'}) # or data.update(request.POST) 
form = MyModelForm(instance=my_model, data=data)
like image 54
Alasdair Avatar answered Sep 07 '26 19:09

Alasdair


Providing the instance argument to a ModelForm is the same as passing initial, i.e. they serve the same purpose. What gets save is always the data. If a field in that dict is empty, then it will be when the model is saved as well.

If you want to maintain the entire state of the model when only dealing with a single field as data. Then, try something like the following:

data = my_model.__dict__
data['bio'] = request.POST.get('bio')
MyModelForm(instance=my_model, data=data)
like image 28
Chris Pratt Avatar answered Sep 07 '26 21:09

Chris Pratt



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!