mirror of
				https://github.com/django/django.git
				synced 2025-10-31 01:25:32 +00:00 
			
		
		
		
	Fixed #21290: Documented migration serializing and improved error
This commit is contained in:
		| @@ -2,6 +2,7 @@ from __future__ import unicode_literals | |||||||
|  |  | ||||||
| import datetime | import datetime | ||||||
| import inspect | import inspect | ||||||
|  | import decimal | ||||||
| from importlib import import_module | from importlib import import_module | ||||||
| import os | import os | ||||||
| import types | import types | ||||||
| @@ -221,6 +222,9 @@ class MigrationWriter(object): | |||||||
|         # Promise |         # Promise | ||||||
|         elif isinstance(value, Promise): |         elif isinstance(value, Promise): | ||||||
|             return repr(force_text(value)), set() |             return repr(force_text(value)), set() | ||||||
|  |         # Decimal | ||||||
|  |         elif isinstance(value, decimal.Decimal): | ||||||
|  |             return repr(value), set(["from decimal import Decimal"]) | ||||||
|         # Django fields |         # Django fields | ||||||
|         elif isinstance(value, models.Field): |         elif isinstance(value, models.Field): | ||||||
|             attr_name, path, args, kwargs = value.deconstruct() |             attr_name, path, args, kwargs = value.deconstruct() | ||||||
| @@ -255,7 +259,7 @@ class MigrationWriter(object): | |||||||
|                 return "%s.%s" % (module, value.__name__), set(["import %s" % module]) |                 return "%s.%s" % (module, value.__name__), set(["import %s" % module]) | ||||||
|         # Uh oh. |         # Uh oh. | ||||||
|         else: |         else: | ||||||
|             raise ValueError("Cannot serialize: %r" % value) |             raise ValueError("Cannot serialize: %r\nThere are some values Django cannot serialize into migration files.\nFor more, see https://docs.djangoproject.com/en/dev/topics/migrations/#migration-serializing" % value) | ||||||
|  |  | ||||||
|  |  | ||||||
| MIGRATION_TEMPLATE = """\ | MIGRATION_TEMPLATE = """\ | ||||||
|   | |||||||
| @@ -281,6 +281,7 @@ Note that this only works given two things: | |||||||
|   that your database doesn't match your models, you'll just get errors when |   that your database doesn't match your models, you'll just get errors when | ||||||
|   migrations try to modify those tables. |   migrations try to modify those tables. | ||||||
|  |  | ||||||
|  |  | ||||||
| .. _historical-models: | .. _historical-models: | ||||||
|  |  | ||||||
| Historical models | Historical models | ||||||
| @@ -302,3 +303,56 @@ so you must always keep base classes around for as long as there is a migration | |||||||
| that contains a reference to them. On the plus side, methods and managers | that contains a reference to them. On the plus side, methods and managers | ||||||
| from these base classes inherit normally, so if you absolutely need access | from these base classes inherit normally, so if you absolutely need access | ||||||
| to these you can opt to move them into a superclass. | to these you can opt to move them into a superclass. | ||||||
|  |  | ||||||
|  |  | ||||||
|  | .. _migration-serializing: | ||||||
|  |  | ||||||
|  | Serializing values | ||||||
|  | ------------------ | ||||||
|  |  | ||||||
|  | Migrations are just Python files containing the old definitions of your models | ||||||
|  | - thus, to write them, Django must take the current state of your models and | ||||||
|  | serialize them out into a file. | ||||||
|  |  | ||||||
|  | While Django can serialize most things, there are some things that we just | ||||||
|  | can't serialize out into a valid Python representation - there's no Python | ||||||
|  | standard for how a value can be turned back into code (``repr()`` only works | ||||||
|  | for basic values, and doesn't specify import paths). | ||||||
|  |  | ||||||
|  | Django can serialize the following: | ||||||
|  |  | ||||||
|  | - ``int``, ``long``, ``float``, ``bool``, ``str``, ``unicode``, ``bytes``, ``None`` | ||||||
|  | - ``list``, ``set``, ``tuple``, ``dict`` | ||||||
|  | - ``datetime.date`` and ``datetime.datetime`` instances | ||||||
|  | - ``decimal.Decimal`` instances | ||||||
|  | - Any Django field | ||||||
|  | - Any function or method reference (e.g. ``datetime.datetime.today``) | ||||||
|  | - Any class reference | ||||||
|  | - Anything with a custom ``deconstruct()`` method (:ref:`see below <custom-deconstruct-method>`) | ||||||
|  |  | ||||||
|  | Django cannot serialize: | ||||||
|  |  | ||||||
|  | - Arbitrary class instances (e.g. ``MyClass(4.3, 5.7)``) | ||||||
|  | - Lambdas | ||||||
|  |  | ||||||
|  | .. _custom-deconstruct-method: | ||||||
|  |  | ||||||
|  | Adding a deconstruct() method | ||||||
|  | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||||||
|  |  | ||||||
|  | You can let Django serialize your own custom class instances by giving the class | ||||||
|  | a ``deconstruct`` method. It takes no arguments, and should return a tuple | ||||||
|  | of 3 things: ``(path, args, kwargs)``. | ||||||
|  |  | ||||||
|  | ``path`` should be the Python path to the class, with the class name included as the | ||||||
|  | last part (for example, ``myapp.custom_things.MyClass``). If your class is not | ||||||
|  | available at the top level of a module it is not serializable. | ||||||
|  |  | ||||||
|  | ``args`` should be a list of positional arguments to pass to your class' | ||||||
|  | ``__init__`` method. Everything in this list should itself be serializable. | ||||||
|  |  | ||||||
|  | ``kwargs`` should be a dict of keyword arguments to pass to your class' | ||||||
|  | ``__init__`` method. Every value should itself be serializable. | ||||||
|  |  | ||||||
|  | Django will write out the value as an instatiation of your class with the | ||||||
|  | given arguments, similar to the way it writes out references to Django fields. | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user