Opened 3 years ago

Closed 3 years ago

Last modified 3 years ago

#32799 closed New feature (wontfix)

Inconsistency regarding the default value of CharField

Reported by: Adam Sołtysik Owned by: nobody
Component: Migrations Version: 3.2
Severity: Normal Keywords:
Cc: Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

Let's assume I want to add a CharField to a model:

class Test(Model):
    # other fields
    name = CharField(max_length=20)

This field is non-nullable and has no default value. However, when an object is created, the field gets an empty string automatically:

>>> Test().name
''

When such an object is saved, an empty string will be saved to the database. The same happens when I call Test.objects.create().

On the other hand, when I create a migration, Django asks me to provide a default. If I omit a default value and try to execute the migration, there will be IntegrityError due to the NOT NULL constraint.

So the question is: why does CharField behave differently in the contexts of Python objects and migrations? The same goes also for FileField, but not e.g. for non-nullable IntegerField (it won't get a value of 0 automatically).

Changing the behaviour of objects with CharField would be a breaking change, but for consistency, I think that migrations should also infer the empty string as the default value, even when there is no default='' or blank=True.

Possibly related: #23405.

Change History (5)

comment:1 by Mariusz Felisiak, 3 years ago

Component: Database layer (models, ORM)Migrations
Resolution: wontfix
Status: newclosed
Type: UncategorizedNew feature

IMO these are two different scenarios. The Django convention is to use the empty string, not NULL. For a string-based field with null=False you have one possible values for "no data" i.e. the empty string that's why Django uses it when value is not provided for a non-nullable string-based field.

Migrations asks for a default value for existing rows when adding a non-nullable field to the model, and does it consistently for all type of fields. Folks can always type '', it's not much of a burden.

You can start a discussion on DevelopersMailingList if you don't agree.

comment:2 by Adam Sołtysik, 3 years ago

IMO these are two different scenarios.

The point is to make these two different scenarios work consistently, not to break the principle of least astonishment. When model objects behave like they have a valid default value, it's surprising that migrations behave like there's no valid default.

For a string-based field with null=False you have one possible values for "no data" i.e. the empty string that's why Django uses it when value is not provided for a non-nullable string-based field.

The same could apply to migrations. Since there's only one possible value for "no data" for the existing rows, it's probably better to use that than to ask for that value or crash.

Migrations asks for a default value for existing rows when adding a non-nullable field to the model, and does it consistently for all type of fields.

Except for the fact that currently blank=True can be used with char fields instead of a default value for the migration to work properly, even though blank parameter is said in the documentation to matter for form validation only.

comment:3 by Adam Sołtysik, 3 years ago

Except for the fact that currently blank=True can be used with char fields instead of a default value for the migration to work properly, even though blank parameter is said ​in the documentation to matter for form validation only.

I've found there was already a ticket about this: #27197, and a discussion on the mailing list: https://groups.google.com/g/django-developers/c/upbDlFgtCHs/discussion, but without any resolution.

comment:4 by Mariusz Felisiak, 3 years ago

The same could apply to migrations. Since there's only one possible value for "no data" for the existing rows, it's probably better to use that than to ask for that value or crash.

It's not the same to use the empty string for a new row and to update all existing rows without asking for a value. With your proposition we would remove an important feature from migrations and we wouldn't give users a chance to decide on their own, which they have when creating a new object.

Again, please start a discussion on DevelopersMailingList if you don't agree.

comment:5 by Adam Sołtysik, 3 years ago

With your proposition we would remove an important feature from migrations and we wouldn't give users a chance to decide on their own

Actually, my proposition is just to make migrations use the same default value that objects use, when there is no explicit default value given. The questioner could still work the same if that's more consistent with other fields. My use case was a migration edited by hand, which crashed due to nulls, when I expected it to use empty strings.

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