Fixed #36806 -- Added system check for null kwarg in GeneratedField.
Some checks are pending
Docs / spelling (push) Waiting to run
Docs / blacken-docs (push) Waiting to run
Docs / lint-docs (push) Waiting to run
Linters / flake8 (push) Waiting to run
Linters / isort (push) Waiting to run
Linters / black (push) Waiting to run
Linters / zizmor (push) Waiting to run
Tests / Windows, SQLite, Python 3.14 (push) Waiting to run
Tests / JavaScript tests (push) Waiting to run

The null argument has no effect on GeneratedField since the nullability
of the column depends on the database and expression used.
This commit is contained in:
Nilesh Kumar Pahari 2025-12-18 16:21:50 +05:30 committed by Jacob Walls
parent afaa527c43
commit 6025eab3c5
4 changed files with 43 additions and 0 deletions

View file

@ -30,6 +30,7 @@ class GeneratedField(Field):
self.expression = expression self.expression = expression
self.output_field = output_field self.output_field = output_field
self.db_persist = db_persist self.db_persist = db_persist
self.has_null_arg = "null" in kwargs
super().__init__(**kwargs) super().__init__(**kwargs)
@cached_property @cached_property
@ -82,6 +83,7 @@ class GeneratedField(Field):
*super().check(**kwargs), *super().check(**kwargs),
*self._check_supported(databases), *self._check_supported(databases),
*self._check_persistence(databases), *self._check_persistence(databases),
*self._check_ignored_options(databases),
] ]
output_field_clone = self.output_field.clone() output_field_clone = self.output_field.clone()
output_field_clone.model = self.model output_field_clone.model = self.model
@ -188,6 +190,20 @@ class GeneratedField(Field):
) )
return errors return errors
def _check_ignored_options(self, databases):
warnings = []
if self.has_null_arg:
warnings.append(
checks.Warning(
"null has no effect on GeneratedField.",
obj=self,
id="fields.W225",
)
)
return warnings
def deconstruct(self): def deconstruct(self):
name, path, args, kwargs = super().deconstruct() name, path, args, kwargs = super().deconstruct()
del kwargs["blank"] del kwargs["blank"]

View file

@ -221,6 +221,7 @@ Model fields
``GeneratedField``\s. ``GeneratedField``\s.
* **fields.E223**: ``GeneratedField.output_field`` has errors: ... * **fields.E223**: ``GeneratedField.output_field`` has errors: ...
* **fields.W224**: ``GeneratedField.output_field`` has warnings: ... * **fields.W224**: ``GeneratedField.output_field`` has warnings: ...
* **fields.W225**: ``null`` has no effect on ``GeneratedField``.
* **fields.E900**: ``IPAddressField`` has been removed except for support in * **fields.E900**: ``IPAddressField`` has been removed except for support in
historical migrations. historical migrations.
* **fields.W900**: ``IPAddressField`` has been deprecated. Support for it * **fields.W900**: ``IPAddressField`` has been deprecated. Support for it

View file

@ -1377,6 +1377,9 @@ materialized view.
backends that support it (SQLite, PostgreSQL, and Oracle) and marked as backends that support it (SQLite, PostgreSQL, and Oracle) and marked as
deferred otherwise. deferred otherwise.
:attr:`~Field.null` has no effect on ``GeneratedField`` since whether the
column is nullable depends on the database and expression used.
``GenericIPAddressField`` ``GenericIPAddressField``
------------------------- -------------------------

View file

@ -1510,3 +1510,26 @@ class GeneratedFieldTests(TestCase):
Model._meta.get_field("field").check(databases={"default"}), Model._meta.get_field("field").check(databases={"default"}),
expected_warnings, expected_warnings,
) )
@skipUnlessDBFeature("supports_stored_generated_columns")
def test_with_null_argument(self):
class Model(models.Model):
value = models.IntegerField()
field = models.GeneratedField(
expression=models.F("value") * 2,
output_field=models.IntegerField(),
db_persist=True,
null=True,
)
expected_warnings = [
DjangoWarning(
"null has no effect on GeneratedField.",
obj=Model._meta.get_field("field"),
id="fields.W225",
),
]
self.assertEqual(
Model._meta.get_field("field").check(databases={"default"}),
expected_warnings,
)