diff --git a/django/db/migrations/serializer.py b/django/db/migrations/serializer.py index 9004d25e21..462f0dd8d1 100644 --- a/django/db/migrations/serializer.py +++ b/django/db/migrations/serializer.py @@ -329,6 +329,18 @@ def serializer_factory(value): # tuple. value = value.__reduce__()[1][0] + if isinstance(value, models.Field): + return ModelFieldSerializer(value) + if isinstance(value, models.manager.BaseManager): + return ModelManagerSerializer(value) + if isinstance(value, Operation): + return OperationSerializer(value) + if isinstance(value, type): + return TypeSerializer(value) + # Anything that knows how to deconstruct itself. + if hasattr(value, 'deconstruct'): + return DeconstructableSerializer(value) + # Unfortunately some of these are order-dependent. if isinstance(value, frozenset): return FrozensetSerializer(value) @@ -362,19 +374,8 @@ def serializer_factory(value): return TextTypeSerializer(value) if isinstance(value, decimal.Decimal): return DecimalSerializer(value) - if isinstance(value, models.Field): - return ModelFieldSerializer(value) - if isinstance(value, type): - return TypeSerializer(value) - if isinstance(value, models.manager.BaseManager): - return ModelManagerSerializer(value) - if isinstance(value, Operation): - return OperationSerializer(value) if isinstance(value, functools.partial): return FunctoolsPartialSerializer(value) - # Anything that knows how to deconstruct itself. - if hasattr(value, 'deconstruct'): - return DeconstructableSerializer(value) if isinstance(value, (types.FunctionType, types.BuiltinFunctionType)): return FunctionTypeSerializer(value) if isinstance(value, collections.Iterable): diff --git a/tests/migrations/test_writer.py b/tests/migrations/test_writer.py index 6c121e0904..8febf40f03 100644 --- a/tests/migrations/test_writer.py +++ b/tests/migrations/test_writer.py @@ -2,6 +2,7 @@ from __future__ import unicode_literals import datetime +import decimal import functools import math import os @@ -35,6 +36,15 @@ except ImportError: enum = None +class Money(decimal.Decimal): + def deconstruct(self): + return ( + '%s.%s' % (self.__class__.__module__, self.__class__.__name__), + [six.text_type(self)], + {} + ) + + class TestModel1(object): def upload_to(self): return "somewhere dynamic" @@ -200,6 +210,18 @@ class WriterTests(SimpleTestCase): self.assertTrue(math.isinf(self.serialize_round_trip(float("-inf")))) self.assertTrue(math.isnan(self.serialize_round_trip(float("nan")))) + self.assertSerializedEqual(decimal.Decimal('1.3')) + self.assertSerializedResultEqual( + decimal.Decimal('1.3'), + ("Decimal('1.3')", {'from decimal import Decimal'}) + ) + + self.assertSerializedEqual(Money('1.3')) + self.assertSerializedResultEqual( + Money('1.3'), + ("migrations.test_writer.Money('1.3')", {'import migrations.test_writer'}) + ) + def test_serialize_constants(self): self.assertSerializedEqual(None) self.assertSerializedEqual(True)