diff --git a/django/db/migrations/operations/models.py b/django/db/migrations/operations/models.py index 8f311b32eaa..e55bfd7f0ed 100644 --- a/django/db/migrations/operations/models.py +++ b/django/db/migrations/operations/models.py @@ -762,7 +762,7 @@ class AddIndex(IndexOperation): def __init__(self, model_name, index): self.model_name = model_name - if not index._name: + if not index.name: raise ValueError( "Indexes passed to AddIndex operations require a name " "argument. %r doesn't have one." % index diff --git a/django/db/models/indexes.py b/django/db/models/indexes.py index 86edc5d1304..694d904a87a 100644 --- a/django/db/models/indexes.py +++ b/django/db/models/indexes.py @@ -3,7 +3,6 @@ from __future__ import unicode_literals import hashlib from django.utils.encoding import force_bytes -from django.utils.functional import cached_property __all__ = ['Index'] @@ -18,31 +17,24 @@ class Index(object): if not fields: raise ValueError('At least one field is required to define an index.') self.fields = fields - self._name = name or '' - if self._name: + self.name = name or '' + if self.name: errors = self.check_name() - if len(self._name) > MAX_NAME_LENGTH: + if len(self.name) > MAX_NAME_LENGTH: errors.append('Index names cannot be longer than %s characters.' % MAX_NAME_LENGTH) if errors: raise ValueError(errors) - @cached_property - def name(self): - if not self._name: - self._name = self.get_name() - self.check_name() - return self._name - def check_name(self): errors = [] # Name can't start with an underscore on Oracle; prepend D if needed. - if self._name[0] == '_': + if self.name[0] == '_': errors.append('Index names cannot start with an underscore (_).') - self._name = 'D%s' % self._name[1:] + self.name = 'D%s' % self.name[1:] # Name can't start with a number on Oracle; prepend D if needed. - elif self._name[0].isdigit(): + elif self.name[0].isdigit(): errors.append('Index names cannot start with a number (0-9).') - self._name = 'D%s' % self._name[1:] + self.name = 'D%s' % self.name[1:] return errors def create_sql(self, model, schema_editor): @@ -81,7 +73,7 @@ class Index(object): h.update(force_bytes(arg)) return h.hexdigest()[:6] - def get_name(self): + def set_name_with_model(self, model): """ Generate a unique name for the index. @@ -89,19 +81,19 @@ class Index(object): (8 chars) and unique hash + suffix (10 chars). Each part is made to fit its size by truncating the excess length. """ - table_name = self.model._meta.db_table - column_names = [self.model._meta.get_field(field).column for field in self.fields] + table_name = model._meta.db_table + column_names = [model._meta.get_field(field).column for field in self.fields] hash_data = [table_name] + column_names + [self.suffix] - index_name = '%s_%s_%s' % ( + self.name = '%s_%s_%s' % ( table_name[:11], column_names[0][:7], '%s_%s' % (self._hash_generator(*hash_data), self.suffix), ) - assert len(index_name) <= 30, ( + assert len(self.name) <= 30, ( 'Index too long for multiple database support. Is self.suffix ' 'longer than 3 characters?' ) - return index_name + self.check_name() def __repr__(self): return "<%s: fields='%s'>" % (self.__class__.__name__, ', '.join(self.fields)) diff --git a/tests/model_indexes/tests.py b/tests/model_indexes/tests.py index 71bd8c91c02..e979a00de77 100644 --- a/tests/model_indexes/tests.py +++ b/tests/model_indexes/tests.py @@ -40,19 +40,19 @@ class IndexesTests(TestCase): def test_name_auto_generation(self): index = models.Index(fields=['author']) - index.model = Book + index.set_name_with_model(Book) self.assertEqual(index.name, 'model_index_author_0f5565_idx') # fields may be truncated in the name. db_column is used for naming. long_field_index = models.Index(fields=['pages']) - long_field_index.model = Book + long_field_index.set_name_with_model(Book) self.assertEqual(long_field_index.name, 'model_index_page_co_69235a_idx') # suffix can't be longer than 3 characters. long_field_index.suffix = 'suff' msg = 'Index too long for multiple database support. Is self.suffix longer than 3 characters?' with self.assertRaisesMessage(AssertionError, msg): - long_field_index.get_name() + long_field_index.set_name_with_model(Book) def test_deconstruction(self): index = models.Index(fields=['title'])