[1.7.x] Fixed #23455 -- Forced related_name to be a unicode string during deconstruction.

Backport of 45bd7b3bd9 from master
This commit is contained in:
Markus Holtermann 2014-09-25 20:21:12 +02:00 committed by Tim Graham
parent 1dec42822c
commit e8a08514de
3 changed files with 21 additions and 3 deletions

View File

@ -14,7 +14,7 @@ from django.db.models.lookups import IsNull
from django.db.models.related import RelatedObject, PathInfo from django.db.models.related import RelatedObject, PathInfo
from django.db.models.query import QuerySet from django.db.models.query import QuerySet
from django.db.models.sql.datastructures import Col from django.db.models.sql.datastructures import Col
from django.utils.encoding import smart_text from django.utils.encoding import force_text, smart_text
from django.utils import six from django.utils import six
from django.utils.deprecation import RenameMethodsBase, RemovedInDjango18Warning from django.utils.deprecation import RenameMethodsBase, RemovedInDjango18Warning
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
@ -1363,7 +1363,7 @@ class ForeignObject(RelatedField):
kwargs['from_fields'] = self.from_fields kwargs['from_fields'] = self.from_fields
kwargs['to_fields'] = self.to_fields kwargs['to_fields'] = self.to_fields
if self.rel.related_name is not None: if self.rel.related_name is not None:
kwargs['related_name'] = self.rel.related_name kwargs['related_name'] = force_text(self.rel.related_name)
if self.rel.related_query_name is not None: if self.rel.related_query_name is not None:
kwargs['related_query_name'] = self.rel.related_query_name kwargs['related_query_name'] = self.rel.related_query_name
if self.rel.on_delete != CASCADE: if self.rel.on_delete != CASCADE:
@ -2099,7 +2099,7 @@ class ManyToManyField(RelatedField):
if self.rel.db_constraint is not True: if self.rel.db_constraint is not True:
kwargs['db_constraint'] = self.rel.db_constraint kwargs['db_constraint'] = self.rel.db_constraint
if self.rel.related_name is not None: if self.rel.related_name is not None:
kwargs['related_name'] = self.rel.related_name kwargs['related_name'] = force_text(self.rel.related_name)
if self.rel.related_query_name is not None: if self.rel.related_query_name is not None:
kwargs['related_query_name'] = self.rel.related_query_name kwargs['related_query_name'] = self.rel.related_query_name
# Rel needs more work. # Rel needs more work.

View File

@ -76,3 +76,7 @@ Bugfixes
* Added ``SchemaEditor`` for MySQL GIS backend so that spatial indexes will be * Added ``SchemaEditor`` for MySQL GIS backend so that spatial indexes will be
created for apps with migrations (:ticket:`23538`). created for apps with migrations (:ticket:`23538`).
* Coerced the ``related_name`` model field option to unicode during migration
generation to generate migrations that work with both Python 2 and 3
(:ticket:`23455`).

View File

@ -1,3 +1,5 @@
from __future__ import unicode_literals
import warnings import warnings
from django.db import models from django.db import models
@ -209,6 +211,12 @@ class FieldDeconstructionTests(TestCase):
self.assertEqual(path, "django.db.models.ForeignKey") self.assertEqual(path, "django.db.models.ForeignKey")
self.assertEqual(args, []) self.assertEqual(args, [])
self.assertEqual(kwargs, {"to": "auth.Permission", "related_name": "foobar"}) self.assertEqual(kwargs, {"to": "auth.Permission", "related_name": "foobar"})
# Test related_name unicode conversion
field = models.ForeignKey("auth.Permission", related_name=b"foobar")
name, path, args, kwargs = field.deconstruct()
self.assertEqual(path, "django.db.models.ForeignKey")
self.assertEqual(args, [])
self.assertEqual(kwargs, {"to": "auth.Permission", "related_name": "foobar"})
@override_settings(AUTH_USER_MODEL="auth.Permission") @override_settings(AUTH_USER_MODEL="auth.Permission")
def test_foreign_key_swapped(self): def test_foreign_key_swapped(self):
@ -289,6 +297,12 @@ class FieldDeconstructionTests(TestCase):
self.assertEqual(path, "django.db.models.ManyToManyField") self.assertEqual(path, "django.db.models.ManyToManyField")
self.assertEqual(args, []) self.assertEqual(args, [])
self.assertEqual(kwargs, {"to": "auth.Permission", "related_name": "custom_table"}) self.assertEqual(kwargs, {"to": "auth.Permission", "related_name": "custom_table"})
# Test related_name unicode conversion
field = models.ManyToManyField("auth.Permission", related_name=b"custom_table")
name, path, args, kwargs = field.deconstruct()
self.assertEqual(path, "django.db.models.ManyToManyField")
self.assertEqual(args, [])
self.assertEqual(kwargs, {"to": "auth.Permission", "related_name": "custom_table"})
@override_settings(AUTH_USER_MODEL="auth.Permission") @override_settings(AUTH_USER_MODEL="auth.Permission")
def test_many_to_many_field_swapped(self): def test_many_to_many_field_swapped(self):