Fixed #28714 -- Added system checks for invalid model field names in Meta.indexes.
Thanks Gabriel for the report and Adam Johnson for the review.
This commit is contained in:
parent
1d00923848
commit
f1aa58479c
|
@ -1203,6 +1203,7 @@ class Model(metaclass=ModelBase):
|
|||
errors += [
|
||||
*cls._check_index_together(),
|
||||
*cls._check_unique_together(),
|
||||
*cls._check_indexes(),
|
||||
*cls._check_ordering(),
|
||||
]
|
||||
|
||||
|
@ -1474,6 +1475,12 @@ class Model(metaclass=ModelBase):
|
|||
errors.extend(cls._check_local_fields(fields, "unique_together"))
|
||||
return errors
|
||||
|
||||
@classmethod
|
||||
def _check_indexes(cls):
|
||||
"""Check the fields of indexes."""
|
||||
fields = [field for index in cls._meta.indexes for field, _ in index.fields_orders]
|
||||
return cls._check_local_fields(fields, 'indexes')
|
||||
|
||||
@classmethod
|
||||
def _check_local_fields(cls, fields, option):
|
||||
from django.db import models
|
||||
|
|
|
@ -265,16 +265,16 @@ Models
|
|||
* **models.E009**: All ``index_together`` elements must be lists or tuples.
|
||||
* **models.E010**: ``unique_together`` must be a list or tuple.
|
||||
* **models.E011**: All ``unique_together`` elements must be lists or tuples.
|
||||
* **models.E012**: ``index_together/unique_together`` refers to the
|
||||
* **models.E012**: ``indexes/index_together/unique_together`` refers to the
|
||||
nonexistent field ``<field name>``.
|
||||
* **models.E013**: ``index_together/unique_together`` refers to a
|
||||
* **models.E013**: ``indexes/index_together/unique_together`` refers to a
|
||||
``ManyToManyField`` ``<field name>``, but ``ManyToManyField``\s are not
|
||||
supported for that option.
|
||||
* **models.E014**: ``ordering`` must be a tuple or list (even if you want to
|
||||
order by only one field).
|
||||
* **models.E015**: ``ordering`` refers to the nonexistent field
|
||||
``<field name>``.
|
||||
* **models.E016**: ``index_together/unique_together`` refers to field
|
||||
* **models.E016**: ``indexes/index_together/unique_together`` refers to field
|
||||
``<field_name>`` which is not local to model ``<model>``.
|
||||
* **models.E017**: Proxy model ``<model>`` contains model fields.
|
||||
* **models.E018**: Autogenerated column name too long for field ``<field>``.
|
||||
|
|
|
@ -219,6 +219,59 @@ class UniqueTogetherTests(SimpleTestCase):
|
|||
])
|
||||
|
||||
|
||||
@isolate_apps('invalid_models_tests')
|
||||
class IndexesTests(SimpleTestCase):
|
||||
|
||||
def test_pointing_to_missing_field(self):
|
||||
class Model(models.Model):
|
||||
class Meta:
|
||||
indexes = [models.Index(fields=['missing_field'], name='name')]
|
||||
|
||||
self.assertEqual(Model.check(), [
|
||||
Error(
|
||||
"'indexes' refers to the nonexistent field 'missing_field'.",
|
||||
obj=Model,
|
||||
id='models.E012',
|
||||
),
|
||||
])
|
||||
|
||||
def test_pointing_to_m2m_field(self):
|
||||
class Model(models.Model):
|
||||
m2m = models.ManyToManyField('self')
|
||||
|
||||
class Meta:
|
||||
indexes = [models.Index(fields=['m2m'], name='name')]
|
||||
|
||||
self.assertEqual(Model.check(), [
|
||||
Error(
|
||||
"'indexes' refers to a ManyToManyField 'm2m', but "
|
||||
"ManyToManyFields are not permitted in 'indexes'.",
|
||||
obj=Model,
|
||||
id='models.E013',
|
||||
),
|
||||
])
|
||||
|
||||
def test_pointing_to_non_local_field(self):
|
||||
class Foo(models.Model):
|
||||
field1 = models.IntegerField()
|
||||
|
||||
class Bar(Foo):
|
||||
field2 = models.IntegerField()
|
||||
|
||||
class Meta:
|
||||
indexes = [models.Index(fields=['field2', 'field1'], name='name')]
|
||||
|
||||
self.assertEqual(Bar.check(), [
|
||||
Error(
|
||||
"'indexes' refers to field 'field1' which is not local to "
|
||||
"model 'Bar'.",
|
||||
hint='This issue may be caused by multi-table inheritance.',
|
||||
obj=Bar,
|
||||
id='models.E016',
|
||||
),
|
||||
])
|
||||
|
||||
|
||||
@isolate_apps('invalid_models_tests')
|
||||
class FieldNamesTests(SimpleTestCase):
|
||||
|
||||
|
|
Loading…
Reference in New Issue