mirror of
https://github.com/django/django.git
synced 2025-11-18 19:01:40 +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):
|
||||
get_field = model._meta.get_field
|
||||
for field_name, *__ in model._get_expr_references(expression):
|
||||
if field_name in exclude:
|
||||
if field_name == "pk":
|
||||
field = model._meta.pk
|
||||
else:
|
||||
field = get_field(field_name)
|
||||
if field_name in exclude or field.name in exclude:
|
||||
return True
|
||||
field = get_field(field_name)
|
||||
if field.generated and cls._expression_refs_exclude(
|
||||
model, field.expression, exclude
|
||||
):
|
||||
|
|
|
|||
|
|
@ -543,3 +543,22 @@ class ConstraintsModel(models.Model):
|
|||
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 (
|
||||
Article,
|
||||
ArticleStatus,
|
||||
AttnameConstraintsModel,
|
||||
Author,
|
||||
Author1,
|
||||
Award,
|
||||
|
|
@ -3766,3 +3767,17 @@ class ConstraintValidationTests(TestCase):
|
|||
self.assertEqual(
|
||||
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