diff options
Diffstat (limited to 'django/apps/registry.py')
| -rw-r--r-- | django/apps/registry.py | 46 |
1 files changed, 26 insertions, 20 deletions
diff --git a/django/apps/registry.py b/django/apps/registry.py index 7ed6e5d468..8a45830ccf 100644 --- a/django/apps/registry.py +++ b/django/apps/registry.py @@ -372,29 +372,35 @@ class Apps(object): The function passed to this method must accept exactly n models as arguments, where n=len(model_keys). """ - # If this function depends on more than one model, we recursively turn - # it into a chain of functions that accept a single model argument and - # pass each in turn to lazy_model_operation. - model_key, more_models = model_keys[0], model_keys[1:] - if more_models: - supplied_fn = function + # Base case: no arguments, just execute the function. + if not model_keys: + function() + # Recursive case: take the head of model_keys, wait for the + # corresponding model class to be imported and registered, then apply + # that argument to the supplied function. Pass the resulting partial + # to lazy_model_operation() along with the remaining model args and + # repeat until all models are loaded and all arguments are applied. + else: + next_model, more_models = model_keys[0], model_keys[1:] - def function(model): - next_function = partial(supplied_fn, model) - # Annotate the function with its field for retrieval in - # migrations.state.StateApps. - if getattr(supplied_fn, 'keywords', None): - next_function.field = supplied_fn.keywords.get('field') + # This will be executed after the class corresponding to next_model + # has been imported and registered. The `func` attribute provides + # duck-type compatibility with partials. + def apply_next_model(model): + next_function = partial(apply_next_model.func, model) self.lazy_model_operation(next_function, *more_models) + apply_next_model.func = function - # If the model is already loaded, pass it to the function immediately. - # Otherwise, delay execution until the class is prepared. - try: - model_class = self.get_registered_model(*model_key) - except LookupError: - self._pending_operations[model_key].append(function) - else: - function(model_class) + # If the model has already been imported and registered, partially + # apply it to the function now. If not, add it to the list of + # pending operations for the model, where it will be executed with + # the model class as its sole argument once the model is ready. + try: + model_class = self.get_registered_model(*next_model) + except LookupError: + self._pending_operations[next_model].append(apply_next_model) + else: + apply_next_model(model_class) def do_pending_operations(self, model): """ |
