mirror of https://github.com/django/django.git
Fixed #35234 -- Added system checks for invalid model field names in ExclusionConstraint.expressions.
This commit is contained in:
parent
0fb104dda2
commit
f82c67aa21
|
@ -77,6 +77,14 @@ class ExclusionConstraint(BaseConstraint):
|
|||
expressions.append(expression)
|
||||
return ExpressionList(*expressions).resolve_expression(query)
|
||||
|
||||
def _check(self, model, connection):
|
||||
references = set()
|
||||
for expr, _ in self.expressions:
|
||||
if isinstance(expr, str):
|
||||
expr = F(expr)
|
||||
references.update(model._get_expr_references(expr))
|
||||
return self._check_references(model, references)
|
||||
|
||||
def _get_condition_sql(self, compiler, schema_editor, query):
|
||||
if self.condition is None:
|
||||
return None
|
||||
|
|
|
@ -2,12 +2,17 @@ import datetime
|
|||
from unittest import mock
|
||||
|
||||
from django.contrib.postgres.indexes import OpClass
|
||||
from django.core.checks import Error
|
||||
from django.core.exceptions import ValidationError
|
||||
from django.db import IntegrityError, NotSupportedError, connection, transaction
|
||||
from django.db.models import (
|
||||
CASCADE,
|
||||
CharField,
|
||||
CheckConstraint,
|
||||
DateField,
|
||||
Deferrable,
|
||||
F,
|
||||
ForeignKey,
|
||||
Func,
|
||||
IntegerField,
|
||||
Model,
|
||||
|
@ -328,6 +333,57 @@ class ExclusionConstraintTests(PostgreSQLTestCase):
|
|||
include="invalid",
|
||||
)
|
||||
|
||||
@isolate_apps("postgres_tests")
|
||||
def test_check(self):
|
||||
class Author(Model):
|
||||
name = CharField(max_length=255)
|
||||
alias = CharField(max_length=255)
|
||||
|
||||
class Meta:
|
||||
app_label = "postgres_tests"
|
||||
|
||||
class Book(Model):
|
||||
title = CharField(max_length=255)
|
||||
published_date = DateField()
|
||||
author = ForeignKey(Author, CASCADE)
|
||||
|
||||
class Meta:
|
||||
app_label = "postgres_tests"
|
||||
constraints = [
|
||||
ExclusionConstraint(
|
||||
name="exclude_check",
|
||||
expressions=[
|
||||
(F("title"), RangeOperators.EQUAL),
|
||||
(F("published_date__year"), RangeOperators.EQUAL),
|
||||
("published_date__month", RangeOperators.EQUAL),
|
||||
(F("author__name"), RangeOperators.EQUAL),
|
||||
("author__alias", RangeOperators.EQUAL),
|
||||
("nonexistent", RangeOperators.EQUAL),
|
||||
],
|
||||
)
|
||||
]
|
||||
|
||||
self.assertCountEqual(
|
||||
Book.check(databases=self.databases),
|
||||
[
|
||||
Error(
|
||||
"'constraints' refers to the nonexistent field 'nonexistent'.",
|
||||
obj=Book,
|
||||
id="models.E012",
|
||||
),
|
||||
Error(
|
||||
"'constraints' refers to the joined field 'author__alias'.",
|
||||
obj=Book,
|
||||
id="models.E041",
|
||||
),
|
||||
Error(
|
||||
"'constraints' refers to the joined field 'author__name'.",
|
||||
obj=Book,
|
||||
id="models.E041",
|
||||
),
|
||||
],
|
||||
)
|
||||
|
||||
def test_repr(self):
|
||||
constraint = ExclusionConstraint(
|
||||
name="exclude_overlapping",
|
||||
|
|
Loading…
Reference in New Issue