As of Django 6.1, having a GeneratedField declared with an explicit null=True causes the warning (fields.W225) null has no effect on GeneratedField.
Consider the following minimal example:
class NumericPrefix(models.Func):
function = "substring"
template = r"%(function)s(%(expressions)s from '^\d+')"
class Foo(models.Model):
code = models.CharField(max_length=50)
code_num_prefix = models.GeneratedField(
expression=NumericPrefix("code"),
output_field=models.CharField(max_length=50),
db_persist=True,
null=True,
)
When I try to resolve this warning by removing null=True, the following happens:
- the
makemigrationscommand prompts the dialog
It is impossible to change a nullable field 'code_num_prefix' on foo to non-nullable without providing a default. This is because the database needs something to populate existing rows.
Please select a fix:
1) Provide a one-off default now (will be set on all existing rows with a null value for this column)
2) Ignore for now. Existing rows that contain NULL values will have to be handled manually, for example with a RunPython or RunSQL operation.
3) Quit and manually define a default value in models.py.
I select 2 because my table contains NULL values that I don’t want to change.
sqlmigrateof the new migration outputs the following SQL:
BEGIN;
--
-- Alter field code_num_prefix on foo
--
ALTER TABLE "foo_foo" ALTER COLUMN "code_num_prefix" SET NOT NULL;
COMMIT;
- attempting to run
migratefails with
django.db.utils.IntegrityError: column "code_num_prefix" of relation "foo_foo" contains null values
(as mentioned above — my table contains NULL values)
I think this is inconsistent with the message of the warning, and is possibly a bug. I believe removing null=True from GeneratedField should be a SQL no-op.