mirror of
				https://github.com/django/django.git
				synced 2025-10-31 09:41:08 +00:00 
			
		
		
		
	[1.9.x] Fixed #25274 --- Made inspectdb handle renamed fields in unique_together.
Backport of 2cb50f935a from master
			
			
This commit is contained in:
		| @@ -71,6 +71,7 @@ class Command(BaseCommand): | ||||
|                 except NotImplementedError: | ||||
|                     constraints = {} | ||||
|                 used_column_names = []  # Holds column names used in the table so far | ||||
|                 column_to_field_name = {}  # Maps column names to names of model fields | ||||
|                 for row in connection.introspection.get_table_description(cursor, table_name): | ||||
|                     comment_notes = []  # Holds Field notes, to be displayed in a Python comment. | ||||
|                     extra_params = OrderedDict()  # Holds Field parameters such as 'db_column'. | ||||
| @@ -83,6 +84,7 @@ class Command(BaseCommand): | ||||
|                     comment_notes.extend(notes) | ||||
|  | ||||
|                     used_column_names.append(att_name) | ||||
|                     column_to_field_name[column_name] = att_name | ||||
|  | ||||
|                     # Add primary_key and unique, if necessary. | ||||
|                     if column_name in indexes: | ||||
| @@ -145,7 +147,7 @@ class Command(BaseCommand): | ||||
|                     if comment_notes: | ||||
|                         field_desc += '  # ' + ' '.join(comment_notes) | ||||
|                     yield '    %s' % field_desc | ||||
|                 for meta_line in self.get_meta(table_name, constraints): | ||||
|                 for meta_line in self.get_meta(table_name, constraints, column_to_field_name): | ||||
|                     yield meta_line | ||||
|  | ||||
|     def normalize_col_name(self, col_name, used_column_names, is_relation): | ||||
| @@ -242,7 +244,7 @@ class Command(BaseCommand): | ||||
|  | ||||
|         return field_type, field_params, field_notes | ||||
|  | ||||
|     def get_meta(self, table_name, constraints): | ||||
|     def get_meta(self, table_name, constraints, column_to_field_name): | ||||
|         """ | ||||
|         Return a sequence comprising the lines of code necessary | ||||
|         to construct the inner Meta class for the model corresponding | ||||
| @@ -255,7 +257,7 @@ class Command(BaseCommand): | ||||
|                 if len(columns) > 1: | ||||
|                     # we do not want to include the u"" or u'' prefix | ||||
|                     # so we build the string rather than interpolate the tuple | ||||
|                     tup = '(' + ', '.join("'%s'" % c for c in columns) + ')' | ||||
|                     tup = '(' + ', '.join("'%s'" % column_to_field_name[c] for c in columns) + ')' | ||||
|                     unique_together.append(tup) | ||||
|         meta = ["", | ||||
|                 "    class Meta:", | ||||
|   | ||||
| @@ -9,4 +9,5 @@ Django 1.8.8 fixes several bugs in 1.8.7. | ||||
| Bugfixes | ||||
| ======== | ||||
|  | ||||
| * ... | ||||
| * Fixed incorrect ``unique_together`` field name generation by ``inspectdb`` | ||||
|   (:ticket:`25274`). | ||||
|   | ||||
| @@ -72,6 +72,13 @@ class ColumnTypes(models.Model): | ||||
| class UniqueTogether(models.Model): | ||||
|     field1 = models.IntegerField() | ||||
|     field2 = models.CharField(max_length=10) | ||||
|     from_field = models.IntegerField(db_column='from') | ||||
|     non_unique = models.IntegerField(db_column='non__unique_column') | ||||
|     non_unique_0 = models.IntegerField(db_column='non_unique__column') | ||||
|  | ||||
|     class Meta: | ||||
|         unique_together = ('field1', 'field2') | ||||
|         unique_together = [ | ||||
|             ('field1', 'field2'), | ||||
|             ('from_field', 'field1'), | ||||
|             ('non_unique', 'non_unique_0'), | ||||
|         ] | ||||
|   | ||||
| @@ -234,10 +234,18 @@ class InspectDBTestCase(TestCase): | ||||
|                      table_name_filter=lambda tn: tn.startswith('inspectdb_uniquetogether'), | ||||
|                      stdout=out) | ||||
|         output = out.getvalue() | ||||
|         self.assertIn( | ||||
|             "        unique_together = (('field1', 'field2'),)", output, | ||||
|             msg='inspectdb should generate unique_together.' | ||||
|         ) | ||||
|         unique_re = re.compile(r'.*unique_together = \((.+),\).*') | ||||
|         unique_together_match = re.findall(unique_re, output) | ||||
|         # There should be one unique_together tuple. | ||||
|         self.assertEqual(len(unique_together_match), 1) | ||||
|         fields = unique_together_match[0] | ||||
|         # Fields with db_column = field name. | ||||
|         self.assertIn("('field1', 'field2')", fields) | ||||
|         # Fields from columns whose names are Python keywords. | ||||
|         self.assertIn("('field1', 'field2')", fields) | ||||
|         # Fields whose names normalize to the same Python field name and hence | ||||
|         # are given an integer suffix. | ||||
|         self.assertIn("('non_unique_column', 'non_unique_column_0')", fields) | ||||
|  | ||||
|     @skipUnless(connection.vendor == 'sqlite', | ||||
|                 "Only patched sqlite's DatabaseIntrospection.data_types_reverse for this test") | ||||
|   | ||||
		Reference in New Issue
	
	Block a user