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 inspect | ||||
| import decimal | ||||
| from importlib import import_module | ||||
| import os | ||||
| import types | ||||
| @@ -221,6 +222,9 @@ class MigrationWriter(object): | ||||
|         # Promise | ||||
|         elif isinstance(value, Promise): | ||||
|             return repr(force_text(value)), set() | ||||
|         # Decimal | ||||
|         elif isinstance(value, decimal.Decimal): | ||||
|             return repr(value), set(["from decimal import Decimal"]) | ||||
|         # Django fields | ||||
|         elif isinstance(value, models.Field): | ||||
|             attr_name, path, args, kwargs = value.deconstruct() | ||||
| @@ -255,7 +259,7 @@ class MigrationWriter(object): | ||||
|                 return "%s.%s" % (module, value.__name__), set(["import %s" % module]) | ||||
|         # Uh oh. | ||||
|         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 = """\ | ||||
|   | ||||
| @@ -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 | ||||
|   migrations try to modify those tables. | ||||
|  | ||||
|  | ||||
| .. _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 | ||||
| from these base classes inherit normally, so if you absolutely need access | ||||
| 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