MCPcopy
hub / github.com/django/django / MigrationAutodetector

Class MigrationAutodetector

django/db/migrations/autodetector.py:43–2066  ·  view source on GitHub ↗

Take a pair of ProjectStates and compare them to see what the first would need doing to make it match the second (the second usually being the project's current state). Note that this naturally operates on entire projects at a time, as it's likely that changes interact (for exa

Source from the content-addressed store, hash-verified

41
42
43class MigrationAutodetector:
44 """
45 Take a pair of ProjectStates and compare them to see what the first would
46 need doing to make it match the second (the second usually being the
47 project's current state).
48
49 Note that this naturally operates on entire projects at a time,
50 as it's likely that changes interact (for example, you can't
51 add a ForeignKey without having a migration to add the table it
52 depends on first). A user interface may offer single-app usage
53 if it wishes, with the caveat that it may not always be possible.
54 """
55
56 def __init__(self, from_state, to_state, questioner=None):
57 self.from_state = from_state
58 self.to_state = to_state
59 self.questioner = questioner or MigrationQuestioner()
60 self.existing_apps = {app for app, model in from_state.models}
61
62 def changes(self, graph, trim_to_apps=None, convert_apps=None, migration_name=None):
63 """
64 Main entry point to produce a list of applicable changes.
65 Take a graph to base names on and an optional set of apps
66 to try and restrict to (restriction is not guaranteed)
67 """
68 changes = self._detect_changes(convert_apps, graph)
69 changes = self.arrange_for_graph(changes, graph, migration_name)
70 if trim_to_apps:
71 changes = self._trim_to_apps(changes, trim_to_apps)
72 return changes
73
74 def deep_deconstruct(self, obj):
75 """
76 Recursive deconstruction for a field and its arguments.
77 Used for full comparison for rename/alter; sometimes a single-level
78 deconstruction will not compare correctly.
79 """
80 if isinstance(obj, list):
81 return [self.deep_deconstruct(value) for value in obj]
82 elif isinstance(obj, tuple):
83 return tuple(self.deep_deconstruct(value) for value in obj)
84 elif isinstance(obj, dict):
85 return {key: self.deep_deconstruct(value) for key, value in obj.items()}
86 elif isinstance(obj, functools.partial):
87 return (
88 obj.func,
89 self.deep_deconstruct(obj.args),
90 self.deep_deconstruct(obj.keywords),
91 )
92 elif isinstance(obj, COMPILED_REGEX_TYPE):
93 return RegexObject(obj)
94 elif isinstance(obj, type):
95 # If this is a type that implements 'deconstruct' as an instance
96 # method, avoid treating this as being deconstructible itself - see
97 # #22951
98 return obj
99 elif hasattr(obj, "deconstruct"):
100 deconstructed = obj.deconstruct()

Calls

no outgoing calls