Code

Opened 5 years ago

Closed 4 years ago

Last modified 7 months ago

#9590 closed Uncategorized (wontfix)

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

Reported by: romke 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 romke 5 years ago.
patch + tests

Download all attachments as: .zip

Change History (7)

Changed 5 years ago by romke

patch + tests

comment:1 Changed 5 years ago by ramiro

  • Needs documentation unset
  • Needs tests unset
  • Patch needs improvement unset

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 5 years ago by mtredinnick

  • Resolution set to wontfix
  • Status changed from new to closed

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 4 years ago by mightyhal

  • Component changed from Forms to Database 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 4 years ago by contact_django@…

  • Has patch set
  • Patch needs improvement set
  • Resolution wontfix deleted
  • Status changed from closed to reopened

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 4 years ago by ubernostrum

  • Resolution set to wontfix
  • Status changed from reopened to closed

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 7 months ago by alepane

  • Easy pickings unset
  • Severity set to Normal
  • Type set to 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

Add Comment

Modify Ticket

Change Properties
<Author field>
Action
as closed
as The resolution will be set. Next status will be 'closed'
The resolution will be deleted. Next status will be 'new'
Author


E-mail address and user name can be saved in the Preferences.

 
Note: See TracTickets for help on using tickets.