summaryrefslogtreecommitdiff
path: root/django/db
diff options
context:
space:
mode:
authorMatt Westcott <matt@west.co.tt>2015-02-14 01:22:38 +0000
committerMarkus Holtermann <info@markusholtermann.eu>2015-05-26 17:10:02 +0200
commitff8a02ae0b33ee52050e22909d432a3aa060d683 (patch)
treebf40de3975777260ff4e55bd9e6459e369bd7c51 /django/db
parent14f20c1fdc894dd348ec6a43eb4e0c5dd854d902 (diff)
Fixed #24340 -- Added nested deconstruction for list, tuple and dict values
Nested deconstruction should recursively deconstruct items within list, tuple and dict values.
Diffstat (limited to 'django/db')
-rw-r--r--django/db/migrations/autodetector.py42
1 files changed, 28 insertions, 14 deletions
diff --git a/django/db/migrations/autodetector.py b/django/db/migrations/autodetector.py
index ad6aeda380..9a4ba42722 100644
--- a/django/db/migrations/autodetector.py
+++ b/django/db/migrations/autodetector.py
@@ -52,21 +52,35 @@ class MigrationAutodetector(object):
Used for full comparison for rename/alter; sometimes a single-level
deconstruction will not compare correctly.
"""
- if not hasattr(obj, 'deconstruct') or isinstance(obj, type):
- return obj
- deconstructed = obj.deconstruct()
- if isinstance(obj, models.Field):
- # we have a field which also returns a name
- deconstructed = deconstructed[1:]
- path, args, kwargs = deconstructed
- return (
- path,
- [self.deep_deconstruct(value) for value in args],
- {
+ if isinstance(obj, list):
+ return [self.deep_deconstruct(value) for value in obj]
+ elif isinstance(obj, tuple):
+ return tuple(self.deep_deconstruct(value) for value in obj)
+ elif isinstance(obj, dict):
+ return {
key: self.deep_deconstruct(value)
- for key, value in kwargs.items()
- },
- )
+ for key, value in obj.items()
+ }
+ elif isinstance(obj, type):
+ # If this is a type that implements 'deconstruct' as an instance method,
+ # avoid treating this as being deconstructible itself - see #22951
+ return obj
+ elif hasattr(obj, 'deconstruct'):
+ deconstructed = obj.deconstruct()
+ if isinstance(obj, models.Field):
+ # we have a field which also returns a name
+ deconstructed = deconstructed[1:]
+ path, args, kwargs = deconstructed
+ return (
+ path,
+ [self.deep_deconstruct(value) for value in args],
+ {
+ key: self.deep_deconstruct(value)
+ for key, value in kwargs.items()
+ },
+ )
+ else:
+ return obj
def only_relation_agnostic_fields(self, fields):
"""