#36350: Custom field's db_check() not taken into account when deciding whether to
recreate constraint.
-------------------------------------+-------------------------------------
Reporter: Baptiste | Owner: (none)
Mispelon |
Type: Bug | Status: assigned
Component: Database | Version: 5.2
layer (models, ORM) |
Severity: Normal | Keywords:
Triage Stage: | Has patch: 0
Unreviewed |
Needs documentation: 0 | Needs tests: 0
Patch needs improvement: 0 | Easy pickings: 0
UI/UX: 0 |
-------------------------------------+-------------------------------------
This is a regression introduced in
9953c804a9375956a542da94665662d306dff48d.
I have a custom field that implements `db_check()` in order to add a
custom db constraint:
{{{#!python
class CharChoiceField(models.CharField):
"""
A custom CharField that automatically creates a db constraint to
guarante
that the stored value respects the field's `choices`.
"""
@property
def non_db_attrs(self):
# Remove `choices` from non_db_attrs so that migrations that only
change
# choices still trigger a db operation and drop/create the
constraint.
attrs = super().non_db_attrs
return tuple({*attrs} - {"choices"})
def db_check(self, connection):
constraint = CheckConstraint(
condition=Q(**{f"{
self.name}__in": dict(self.choices)}),
name="", # doesn't matter, Django will reassign one anyway
)
with connection.schema_editor() as schema_editor:
return constraint.get_check_sql(self.model, schema_editor)
}}}
This used to work well (in Django < 5.0): the constraint was added
alongside the field when the initial migration was run, and any changes to
the field's `choices` would trigger a new migration (that's standard
Django behavior) which when executed would drop/create the constraint with
the new value of `choices`.
However the commit I linked to at the beginning broke this: now any
changes to `choices` still creates a migration, but executing the
migration is now a no-op (which can be confirmed by checking with
`sqlmigrate`).
I'm not sure if `Field.db_check()` can be considered public API (it's not
documented), but I have a fix which is fairly simple (PR incoming) so I
hope you'll consider it.
--
Ticket URL: <
https://code.djangoproject.com/ticket/36350>
Django <
https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.