Browse Source

Fixed #27378 -- Added support for serialization of uuid.UUID in migrations.

Thanks Yuriy Korobko for the initial patch and Tobias McNulty for review.
Maxime Lorant 8 years ago
parent
commit
cb3fb34b86

+ 8 - 0
django/db/migrations/serializer.py

@@ -6,6 +6,7 @@ import decimal
 import functools
 import math
 import types
+import uuid
 from importlib import import_module
 
 from django.db import models
@@ -320,6 +321,11 @@ class TypeSerializer(BaseSerializer):
                 return "%s.%s" % (module, self.value.__name__), {"import %s" % module}
 
 
+class UUIDSerializer(BaseSerializer):
+    def serialize(self):
+        return "uuid.%s" % repr(self.value), {"import uuid"}
+
+
 def serializer_factory(value):
     from django.db.migrations.writer import SettingsReference
     if isinstance(value, Promise):
@@ -382,6 +388,8 @@ def serializer_factory(value):
         return IterableSerializer(value)
     if isinstance(value, (COMPILED_REGEX_TYPE, RegexObject)):
         return RegexSerializer(value)
+    if isinstance(value, uuid.UUID):
+        return UUIDSerializer(value)
     raise ValueError(
         "Cannot serialize: %r\nThere are some values Django cannot serialize into "
         "migration files.\nFor more, see https://docs.djangoproject.com/en/%s/"

+ 1 - 1
docs/releases/1.11.txt

@@ -286,7 +286,7 @@ Management Commands
 Migrations
 ~~~~~~~~~~
 
-* ...
+* Added support for serialization of ``uuid.UUID`` objects.
 
 Models
 ~~~~~~

+ 5 - 0
docs/topics/migrations.txt

@@ -670,6 +670,7 @@ Django can serialize the following:
   (include those that are timezone-aware)
 - ``decimal.Decimal`` instances
 - ``enum.Enum`` instances
+- ``uuid.UUID`` instances
 - ``functools.partial`` instances which have serializable ``func``, ``args``,
   and ``keywords`` values.
 - ``LazyObject`` instances which wrap a serializable value.
@@ -682,6 +683,10 @@ Django can serialize the following:
 
     Serialization support for ``enum.Enum`` was added.
 
+.. versionchanged:: 1.11
+
+    Serialization support for ``uuid.UUID`` was added.
+
 Django can serialize the following on Python 3 only:
 
 - Unbound methods used from within the class body (see below)

+ 26 - 0
tests/migrations/test_writer.py

@@ -10,6 +10,7 @@ import re
 import sys
 import tokenize
 import unittest
+import uuid
 
 import custom_migration_operations.more_operations
 import custom_migration_operations.operations
@@ -321,6 +322,31 @@ class WriterTests(SimpleTestCase):
             "default=migrations.test_writer.IntEnum(1))"
         )
 
+    def test_serialize_uuid(self):
+        self.assertSerializedEqual(uuid.uuid1())
+        self.assertSerializedEqual(uuid.uuid4())
+
+        uuid_a = uuid.UUID('5c859437-d061-4847-b3f7-e6b78852f8c8')
+        uuid_b = uuid.UUID('c7853ec1-2ea3-4359-b02d-b54e8f1bcee2')
+        self.assertSerializedResultEqual(
+            uuid_a,
+            ("uuid.UUID('5c859437-d061-4847-b3f7-e6b78852f8c8')", {'import uuid'})
+        )
+        self.assertSerializedResultEqual(
+            uuid_b,
+            ("uuid.UUID('c7853ec1-2ea3-4359-b02d-b54e8f1bcee2')", {'import uuid'})
+        )
+
+        field = models.UUIDField(choices=((uuid_a, 'UUID A'), (uuid_b, 'UUID B')), default=uuid_a)
+        string = MigrationWriter.serialize(field)[0]
+        self.assertEqual(
+            string,
+            "models.UUIDField(choices=["
+            "(uuid.UUID('5c859437-d061-4847-b3f7-e6b78852f8c8'), 'UUID A'), "
+            "(uuid.UUID('c7853ec1-2ea3-4359-b02d-b54e8f1bcee2'), 'UUID B')], "
+            "default=uuid.UUID('5c859437-d061-4847-b3f7-e6b78852f8c8'))"
+        )
+
     def test_serialize_functions(self):
         with self.assertRaisesMessage(ValueError, 'Cannot serialize function: lambda'):
             self.assertSerializedEqual(lambda x: 42)