From ff8a02ae0b33ee52050e22909d432a3aa060d683 Mon Sep 17 00:00:00 2001 From: Matt Westcott Date: Sat, 14 Feb 2015 01:22:38 +0000 Subject: Fixed #24340 -- Added nested deconstruction for list, tuple and dict values Nested deconstruction should recursively deconstruct items within list, tuple and dict values. --- django/db/migrations/autodetector.py | 42 ++++++++++++++++++++++++------------ 1 file changed, 28 insertions(+), 14 deletions(-) (limited to 'django') 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): """ -- cgit v1.3