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): def __init__(self, model_name, index):
self.model_name = model_name self.model_name = model_name
if not index._name: if not index.name:
raise ValueError( raise ValueError(
"Indexes passed to AddIndex operations require a name " "Indexes passed to AddIndex operations require a name "
"argument. %r doesn't have one." % index "argument. %r doesn't have one." % index

View File

@ -3,7 +3,6 @@ from __future__ import unicode_literals
import hashlib import hashlib
from django.utils.encoding import force_bytes from django.utils.encoding import force_bytes
from django.utils.functional import cached_property
__all__ = ['Index'] __all__ = ['Index']
@ -18,31 +17,24 @@ class Index(object):
if not fields: if not fields:
raise ValueError('At least one field is required to define an index.') raise ValueError('At least one field is required to define an index.')
self.fields = fields self.fields = fields
self._name = name or '' self.name = name or ''
if self._name: if self.name:
errors = self.check_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) errors.append('Index names cannot be longer than %s characters.' % MAX_NAME_LENGTH)
if errors: if errors:
raise ValueError(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): def check_name(self):
errors = [] errors = []
# Name can't start with an underscore on Oracle; prepend D if needed. # 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 (_).') 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. # 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).') 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 return errors
def create_sql(self, model, schema_editor): def create_sql(self, model, schema_editor):
@ -81,7 +73,7 @@ class Index(object):
h.update(force_bytes(arg)) h.update(force_bytes(arg))
return h.hexdigest()[:6] return h.hexdigest()[:6]
def get_name(self): def set_name_with_model(self, model):
""" """
Generate a unique name for the index. 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 (8 chars) and unique hash + suffix (10 chars). Each part is made to
fit its size by truncating the excess length. fit its size by truncating the excess length.
""" """
table_name = self.model._meta.db_table table_name = model._meta.db_table
column_names = [self.model._meta.get_field(field).column for field in self.fields] column_names = [model._meta.get_field(field).column for field in self.fields]
hash_data = [table_name] + column_names + [self.suffix] hash_data = [table_name] + column_names + [self.suffix]
index_name = '%s_%s_%s' % ( self.name = '%s_%s_%s' % (
table_name[:11], table_name[:11],
column_names[0][:7], column_names[0][:7],
'%s_%s' % (self._hash_generator(*hash_data), self.suffix), '%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 ' 'Index too long for multiple database support. Is self.suffix '
'longer than 3 characters?' 'longer than 3 characters?'
) )
return index_name self.check_name()
def __repr__(self): def __repr__(self):
return "<%s: fields='%s'>" % (self.__class__.__name__, ', '.join(self.fields)) 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): def test_name_auto_generation(self):
index = models.Index(fields=['author']) index = models.Index(fields=['author'])
index.model = Book index.set_name_with_model(Book)
self.assertEqual(index.name, 'model_index_author_0f5565_idx') self.assertEqual(index.name, 'model_index_author_0f5565_idx')
# fields may be truncated in the name. db_column is used for naming. # fields may be truncated in the name. db_column is used for naming.
long_field_index = models.Index(fields=['pages']) 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') self.assertEqual(long_field_index.name, 'model_index_page_co_69235a_idx')
# suffix can't be longer than 3 characters. # suffix can't be longer than 3 characters.
long_field_index.suffix = 'suff' long_field_index.suffix = 'suff'
msg = 'Index too long for multiple database support. Is self.suffix longer than 3 characters?' msg = 'Index too long for multiple database support. Is self.suffix longer than 3 characters?'
with self.assertRaisesMessage(AssertionError, msg): with self.assertRaisesMessage(AssertionError, msg):
long_field_index.get_name() long_field_index.set_name_with_model(Book)
def test_deconstruction(self): def test_deconstruction(self):
index = models.Index(fields=['title']) index = models.Index(fields=['title'])