Opened 2 days ago

Last modified 3 hours ago

#36806 assigned Cleanup/optimization

Add system check for null kwarg in GeneratedField definition

Reported by: Dai-Tado Owned by: Nilesh Pahari
Component: Database layer (models, ORM) Version: 5.2
Severity: Normal Keywords: GeneratedField
Cc: Triage Stage: Accepted
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

Summary
GeneratedField ignores null=False on MySQL - columns are always nullable

Description
When creating a GeneratedField with null=False on MySQL, the database column is always created as nullable, ignoring the null=False parameter.
Steps to Reproduce

pythonfrom django.db import models

class MyModel(models.Model):
    area = models.GeneratedField(
        .....
        null=False,  # ← Ignored
    )
  • The migration file removes null=False from GeneratedField definition
  • Even if manually added to migration file, Django doesn't apply NOT NULL constraint to database

Change History (9)

comment:1 by Dai-Tado, 2 days ago

Summary: GeneratedField with null=False creates nullable column on MySQL with spatial types (POINT)GeneratedField with null=False creates nullable column on MySQL

comment:2 by Dai-Tado, 2 days ago

If this is the expected behavior, would it be possible to include this in the official documentation?

comment:3 by Jacob Walls, 2 days ago

Summary: GeneratedField with null=False creates nullable column on MySQLAdd system check for null kwarg in GeneratedField definition
Type: BugCleanup/optimization

Good idea, I would be happy to accept something similar to what we have for ManyToManyField, e.g.:

  • django/db/models/fields/generated.py

    diff --git a/django/db/models/fields/generated.py b/django/db/models/fields/generated.py
    index f89269b5e6..551302475b 100644
    a b class GeneratedField(Field):  
    3030        self.expression = expression
    3131        self.output_field = output_field
    3232        self.db_persist = db_persist
     33        self.has_null = "null" in kwargs
    3334        super().__init__(**kwargs)
    3435
    3536    @cached_property
    class GeneratedField(Field):  
    8283            *super().check(**kwargs),
    8384            *self._check_supported(databases),
    8485            *self._check_persistence(databases),
     86            *self._check_ignored_options(databases),
    8587        ]
    8688        output_field_clone = self.output_field.clone()
    8789        output_field_clone.model = self.model
    class GeneratedField(Field):  
    188190                )
    189191        return errors
    190192
     193    def _check_ignored_options(self, **kwargs):
     194        warnings = []
     195
     196        if self.has_null_arg:
     197            warnings.append(
     198                checks.Warning(
     199                    "null has no effect on GeneratedField.",
     200                    obj=self,
     201                    id="fields.WXXX",
     202                )
     203            )
     204
     205        return warnings
     206
    191207    def deconstruct(self):
    192208        name, path, args, kwargs = super().deconstruct()
    193209        del kwargs["blank"]

Would you like to submit a PR and add a test? You should be able to riff on the docs & tests for ManyToMany from 011abb7d96c75f6154c15a8a0f997d8c27698679 (#19671).

comment:4 by Jacob Walls, 2 days ago

Keywords: GeneratedField added
Triage Stage: UnreviewedAccepted

comment:5 by Nilesh Pahari, 43 hours ago

Owner: set to Nilesh Pahari
Status: newassigned

comment:6 by Nilesh Pahari, 24 hours ago

Needs documentation: set
Needs tests: set

comment:7 by Nilesh Pahari, 5 hours ago

Has patch: set

comment:9 by Jacob Walls, 3 hours ago

Needs documentation: unset
Needs tests: unset
Note: See TracTickets for help on using tickets.
Back to Top