Opened 8 years ago

Closed 7 years ago

Last modified 6 months ago

#9590 closed Uncategorized (wontfix)

CharField and TextField with blank=True, null=True saves u'' instead of null

Reported by: Roman Barczyński Owned by: nobody
Component: Database layer (models, ORM) Version: 1.0
Severity: Normal Keywords: charfield, textfield, null
Cc: Triage Stage: Unreviewed
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: yes
Easy pickings: no UI/UX: no

Description

Create model and form:

class Test(models.Model):
    testfield = models.CharField(max_length=20, null=True, blank=True)
    testfield2 = models.TextField(null=True, blank=True)
class NullCharFieldForm(forms.ModelForm):
  class Meta:
    model = Test
    fields = ('testfield', 'testfield2',)

Now create object from POST-alike data (empty input or textarea = ""):

>>> form = NullCharFieldForm({'testfield':'', 'testfield2': ''})
>>> form.is_valid()
True
>>> obj = form.save()
>>> obj.testfield
u''
>>> obj.testfield2
u''

form validates as it should with blank=True but it stores u"" in object fields and in DATABASE :/

result should be:

>>> obj.testfield
>>>
>>> obj.testfield is None
True

Patch + tests attached, it's created on 1.0.X branch, it passes against model_forms and forms (regression) tests.

Attachments (1)

char-text-field-null-value-save-null.patch (3.2 KB) - added by Roman Barczyński 8 years ago.
patch + tests

Download all attachments as: .zip

Change History (10)

Changed 8 years ago by Roman Barczyński

patch + tests

comment:1 Changed 8 years ago by Ramiro Morales

I think this behavior ir related to the convention used by Django for CharField's and TextField's with no value, the rationale is explained in the section of documentation that describes the null field option:

http://docs.djangoproject.com/en/dev/ref/models/fields/#null

comment:2 Changed 8 years ago by Malcolm Tredinnick

Resolution: wontfix
Status: newclosed

This is by design and fully documented. If you want to save NULLs in a text-based field, you'll need to create your own Field subclass. Changing the existing Django behaviour would be backwards-incompatible.

comment:3 Changed 7 years ago by mightyhal

Component: FormsDatabase layer (models, ORM)
Has patch: unset

I agree that it's pretty annoying that django forces for empty string fields, even when null=True, blank=True is set. Following mtredinnick's suggestion (and some teeth grinding), here's how to subclass a CharField to make it store NULL:

from django.db import models

class CharNullField(models.CharField):
	description = "CharField that stores NULL but returns ''"
	def to_python(self, value):
		if isinstance(value, models.CharField):
			return value 
		if value==None:
			return ""
		else:
			return value
	def get_db_prep_value(self, value):
		if value=="":
			return None
		else:
			return value

comment:4 Changed 7 years ago by contact_django@…

Has patch: set
Patch needs improvement: set
Resolution: wontfix
Status: closedreopened

The behavior is contrary to documentation.
When a field has null=True, django should store a NULL value, as documented.
Documentation says "Avoid using null on string-based fields such as CharField and TextField unless you have an excellent reason." When you have a legacy database, you may be in a situation when you don't have the choice. This is my case. Actually I even have a database integrity check field<>[[BR]]

If you really really don't want to support null=True for these kind of fields, you should fix the documentation and issue an error when a null=True is found in a CharField.

comment:5 Changed 7 years ago by James Bennett

Resolution: wontfix
Status: reopenedclosed

Don't reopen a ticket which has been closed as "wontfix" by a committer. If you disagree, bring up the issue on the django-developers mailing list.

comment:6 Changed 3 years ago by alepane

Easy pickings: unset
Severity: Normal
Type: Uncategorized
UI/UX: unset

If you need a nullable CharField, you can use this small app that I made https://github.com/alepane21/django-nullablecharfield

comment:7 Changed 20 months ago by Josh

Thanks goodness for Google search!

This inconsistency was driving me mad. As a new django dev, I thought I was doing something wrong. Good to know it's not me--it's backward's compatibility. From a long, long, long time ago. This should be mentioned with a bright red warning label in the documentation.

comment:8 Changed 20 months ago by Josh Smeaton

It is documented:

Avoid using null on string-based fields such as CharField and TextField because empty string values will always be stored as empty strings, not as NULL. ... the Django convention is to use the empty string, not NULL.

comment:9 Changed 6 months ago by Jon Dufresne

To anyone reading this ticket looking for a solution. The following commit may provide an alternative path to solve the same problem.

https://github.com/django/django/commit/267dc4adddd2882182f71a7f285a06b1d4b15af0

Relevant ticket: #4136

Note: See TracTickets for help on using tickets.
Back to Top