#Can't use non nullable field (null=False)

25 messages · Page 1 of 1 (latest)

spiral nimbus
#

Hello!
Anyone knows why Django ORM force me to set default when I add new non-nullable field (null=False) to an existing model.
For example

# previous code with applied migration
class Promotion(models.Model):
  name = models.CharField(max_length=255)
# added new field
class Promotion(models.Model):
  name = models.CharField(max_length=255)
  category = models.CharField(max_length=255)
  is_own_fund = models.BooleanField()

That's the case too if I add non nullable ForeigKey.
It is always prompting for default values when I try to make new migrations

#

Can't use non nullable field (null=False)

digital torrent
#

The ORM forces a default since it assumes data might have been added to the model (table) in between the 2 migrations and therefore any existing rows require a default value to be present.

You have the option to add a single default or you do the following:

  1. Add the field as nullable
  2. Write a data migration to back fill the data
  3. Make the field non-nullable.
spiral nimbus
#

Thanks but in my case the fields are news, if I modify an existing field I understand that behavior but for new field added it is annoying for me.
And in case of ForeignKey should i pass a fake id for values for example?

digital torrent
#

I am referring to new fields. Django doesn't make any assumptions about the time that has passed between migrations, they are snapshots in time.

spiral nimbus
digital torrent
#

I would take data integrity over annoying anyday.... Once you get more familiar with Django's migrations then this will become less of a problem 🙂

spiral nimbus
#

Data integrity is not a problem in case of a new field added (The column did not exist before, so there wasn't any data in the db for that column. ).
In case of a modified column, it can make sense as the column might contain NULL values before that.

digital torrent
#

Data integrity would be a problem for a new field if Django didn't force you to specify a default for a non-null field! This is why Django asks the question!

spiral nimbus
#

Why 🥲? As I said before, if I add a new field: — There is no migration that contain that field before.
— And there is no possible data yet on that table as the column did not exist yet.

By data integrity in this situation, I mean: the column might contain NULL but the column is defined as not nullable

That kind of things cannot happen for a new field.

#

I just wanna know how a data integrity issue can happen in that case

digital torrent
#

If you already have some rows, then add a new column, what happens to the existing rows?

fair reef
#

We're both working on a project
You have no data in the table
I have data in the table
You add a new field, you expect that it doesn't affect you
But it will affect me.

How will the system handle it?

spiral nimbus
#

Let's take an example:
I have table
Promotion:
- name (column)

the column name data are: "John", "BOB", "Alice"

if i add a new column called category the query that run under the hood is just an alter table

ALTER TABLE Promotion
ADD category varchar(255);

The existing data in the table are not impacted at all.
The column category wouldn't have any data as it is a new column/field, it did not exist before the migration.

chilly elk
#

A row cannot have "no data" in SQL.

#

It can be null, or blank (""), but those are still values.

fair reef
spiral nimbus
# chilly elk A row cannot have "no data" in SQL.

yes i understand that. But i our case The user cannot insert data with null value. The insert must have a value
Insert Promotion values

INSERT Promotion table VALUES ("dylan", "category3")

THIS WIL not work

INSERT Promotion table VALUES ("dylan", null)
chilly elk
#

sqlite3 ':memory:
It's still an SQL limitation, not Django arbitrarily choosing to prevent you from doing it.

sqlite> create table promotion (id integer primary key, name varchar(255));
sqlite> insert into promotion (name) values ('alice'), ('bob'), ('charlie');
sqlite> select * from promotion ;
1|alice
2|bob
3|charlie
sqlite> alter TABLE promotion add COLUMN description not null;
Runtime error: Cannot add a NOT NULL column with default value NULL
#
sqlite> alter TABLE promotion add COLUMN description not null default '';
sqlite> select * from promotion ;
1|alice|
2|bob|
3|charlie|
#

Now, this works in SQLite if you don't have data.

sqlite> drop table promotion ;
sqlite> .schema
sqlite> create table promotion (id integer primary key, name varchar(255));
sqlite> alter TABLE promotion add COLUMN description not null;
sqlite> insert into promotion (name) values ('alice'), ('bob'), ('charlie'); -- fails as expected
Runtime error: NOT NULL constraint failed: promotion.description (19)
#

But as migrations are meant to be shipped as part of your code base, makemigrations (on your dev machine) cannot make assumptions on whether there will be data when you apply them via migrate (e.g. on your production server).

spiral nimbus
#

Thank you so much! That makes things clearer for me. I wasn't aware of it before, but I'll definitely take note of it now.

#

Thank you @digital torrent , @fair reef , and @chilly elk for your help. Apologies for taking up some of your time 🥲 .

chilly elk
#

It's what we're here for, no need to apologize 🙂