mirror of
https://github.com/django/django.git
synced 2025-11-19 03:08:59 +00:00
Fixed #36730 -- Fixed constraint validation crash for excluded FK attnames.
Regression in e44e8327d3.
Co-authored-by: Mariusz Felisiak <felisiak.mariusz@gmail.com>
This commit is contained in:
parent
5401b125ab
commit
abfa4619fb
3 changed files with 39 additions and 2 deletions
|
|
@ -51,9 +51,12 @@ class BaseConstraint:
|
||||||
def _expression_refs_exclude(cls, model, expression, exclude):
|
def _expression_refs_exclude(cls, model, expression, exclude):
|
||||||
get_field = model._meta.get_field
|
get_field = model._meta.get_field
|
||||||
for field_name, *__ in model._get_expr_references(expression):
|
for field_name, *__ in model._get_expr_references(expression):
|
||||||
if field_name in exclude:
|
if field_name == "pk":
|
||||||
return True
|
field = model._meta.pk
|
||||||
|
else:
|
||||||
field = get_field(field_name)
|
field = get_field(field_name)
|
||||||
|
if field_name in exclude or field.name in exclude:
|
||||||
|
return True
|
||||||
if field.generated and cls._expression_refs_exclude(
|
if field.generated and cls._expression_refs_exclude(
|
||||||
model, field.expression, exclude
|
model, field.expression, exclude
|
||||||
):
|
):
|
||||||
|
|
|
||||||
|
|
@ -543,3 +543,22 @@ class ConstraintsModel(models.Model):
|
||||||
violation_error_message="Price must be greater than zero.",
|
violation_error_message="Price must be greater than zero.",
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
class AttnameConstraintsModel(models.Model):
|
||||||
|
left = models.ForeignKey(
|
||||||
|
"self", related_name="+", null=True, on_delete=models.SET_NULL
|
||||||
|
)
|
||||||
|
right = models.ForeignKey(
|
||||||
|
"self", related_name="+", null=True, on_delete=models.SET_NULL
|
||||||
|
)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
required_db_features = {"supports_table_check_constraints"}
|
||||||
|
constraints = [
|
||||||
|
models.CheckConstraint(
|
||||||
|
name="%(app_label)s_%(class)s_left_not_right",
|
||||||
|
# right_id here is the ForeignKey's attname, not name.
|
||||||
|
condition=~models.Q(left=models.F("right_id")),
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,7 @@ from django.utils.version import PY314, PYPY
|
||||||
from .models import (
|
from .models import (
|
||||||
Article,
|
Article,
|
||||||
ArticleStatus,
|
ArticleStatus,
|
||||||
|
AttnameConstraintsModel,
|
||||||
Author,
|
Author,
|
||||||
Author1,
|
Author1,
|
||||||
Award,
|
Award,
|
||||||
|
|
@ -3766,3 +3767,17 @@ class ConstraintValidationTests(TestCase):
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
full_form.errors, {"__all__": ["Price must be greater than zero."]}
|
full_form.errors, {"__all__": ["Price must be greater than zero."]}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def test_check_constraint_refs_excluded_field_attname(self):
|
||||||
|
left = AttnameConstraintsModel.objects.create()
|
||||||
|
instance = AttnameConstraintsModel.objects.create(left=left)
|
||||||
|
data = {
|
||||||
|
"left": str(left.id),
|
||||||
|
"right": "",
|
||||||
|
}
|
||||||
|
AttnameConstraintsModelForm = modelform_factory(
|
||||||
|
AttnameConstraintsModel, fields="__all__"
|
||||||
|
)
|
||||||
|
full_form = AttnameConstraintsModelForm(data, instance=instance)
|
||||||
|
self.assertFalse(full_form.is_valid())
|
||||||
|
self.assertEqual(full_form.errors, {"right": ["This field is required."]})
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue