Refs #26709 -- Replaced Index.get_name() with set_name_with_model().

This removes the dependency of the Index class on its 'model'
attribute.
This commit is contained in:
Akshesh 2016-07-18 19:59:47 +05:30 committed by Tim Graham
parent ef92ed530e
commit b92c6b7d56
3 changed files with 17 additions and 25 deletions

View File

@ -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

View File

@ -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))

View File

@ -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'])