mirror of
https://github.com/django/django.git
synced 2025-01-18 06:12:23 +00:00
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)
|
expressions.append(expression)
|
||||||
return ExpressionList(*expressions).resolve_expression(query)
|
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):
|
def _get_condition_sql(self, compiler, schema_editor, query):
|
||||||
if self.condition is None:
|
if self.condition is None:
|
||||||
return None
|
return None
|
||||||
|
@ -2,12 +2,17 @@ import datetime
|
|||||||
from unittest import mock
|
from unittest import mock
|
||||||
|
|
||||||
from django.contrib.postgres.indexes import OpClass
|
from django.contrib.postgres.indexes import OpClass
|
||||||
|
from django.core.checks import Error
|
||||||
from django.core.exceptions import ValidationError
|
from django.core.exceptions import ValidationError
|
||||||
from django.db import IntegrityError, NotSupportedError, connection, transaction
|
from django.db import IntegrityError, NotSupportedError, connection, transaction
|
||||||
from django.db.models import (
|
from django.db.models import (
|
||||||
|
CASCADE,
|
||||||
|
CharField,
|
||||||
CheckConstraint,
|
CheckConstraint,
|
||||||
|
DateField,
|
||||||
Deferrable,
|
Deferrable,
|
||||||
F,
|
F,
|
||||||
|
ForeignKey,
|
||||||
Func,
|
Func,
|
||||||
IntegerField,
|
IntegerField,
|
||||||
Model,
|
Model,
|
||||||
@ -328,6 +333,57 @@ class ExclusionConstraintTests(PostgreSQLTestCase):
|
|||||||
include="invalid",
|
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):
|
def test_repr(self):
|
||||||
constraint = ExclusionConstraint(
|
constraint = ExclusionConstraint(
|
||||||
name="exclude_overlapping",
|
name="exclude_overlapping",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user