web/lib/django/db/models/loading.py
changeset 29 cc9b7e14412b
parent 0 0d40e90630ef
equal deleted inserted replaced
28:b758351d191f 29:cc9b7e14412b
     2 
     2 
     3 from django.conf import settings
     3 from django.conf import settings
     4 from django.core.exceptions import ImproperlyConfigured
     4 from django.core.exceptions import ImproperlyConfigured
     5 from django.utils.datastructures import SortedDict
     5 from django.utils.datastructures import SortedDict
     6 from django.utils.importlib import import_module
     6 from django.utils.importlib import import_module
     7 
     7 from django.utils.module_loading import module_has_submodule
       
     8 
       
     9 import imp
     8 import sys
    10 import sys
     9 import os
    11 import os
    10 import threading
    12 import threading
    11 
    13 
    12 __all__ = ('get_apps', 'get_app', 'get_models', 'get_model', 'register_models',
    14 __all__ = ('get_apps', 'get_app', 'get_models', 'get_model', 'register_models',
    33         loaded = False,
    35         loaded = False,
    34         handled = {},
    36         handled = {},
    35         postponed = [],
    37         postponed = [],
    36         nesting_level = 0,
    38         nesting_level = 0,
    37         write_lock = threading.RLock(),
    39         write_lock = threading.RLock(),
       
    40         _get_models_cache = {},
    38     )
    41     )
    39 
    42 
    40     def __init__(self):
    43     def __init__(self):
    41         self.__dict__ = self.__shared_state
    44         self.__dict__ = self.__shared_state
    42 
    45 
    68         Loads the app with the provided fully qualified name, and returns the
    71         Loads the app with the provided fully qualified name, and returns the
    69         model module.
    72         model module.
    70         """
    73         """
    71         self.handled[app_name] = None
    74         self.handled[app_name] = None
    72         self.nesting_level += 1
    75         self.nesting_level += 1
       
    76         app_module = import_module(app_name)
    73         try:
    77         try:
    74             models = import_module('.models', app_name)
    78             models = import_module('.models', app_name)
    75         except ImportError:
    79         except ImportError:
    76             self.nesting_level -= 1
    80             self.nesting_level -= 1
    77             if can_postpone:
    81             # If the app doesn't have a models module, we can just ignore the
    78                 # Either the app has no models, or the package is still being
    82             # ImportError and return no models for it.
    79                 # imported by Python and the model module isn't available yet.
    83             if not module_has_submodule(app_module, 'models'):
    80                 # We will check again once all the recursion has finished (in
    84                 return None
    81                 # populate).
    85             # But if the app does have a models module, we need to figure out
    82                 self.postponed.append(app_name)
    86             # whether to suppress or propagate the error. If can_postpone is
    83             return None
    87             # True then it may be that the package is still being imported by
       
    88             # Python and the models module isn't available yet. So we add the
       
    89             # app to the postponed list and we'll try it again after all the
       
    90             # recursion has finished (in populate). If can_postpone is False
       
    91             # then it's time to raise the ImportError.
       
    92             else:
       
    93                 if can_postpone:
       
    94                     self.postponed.append(app_name)
       
    95                     return None
       
    96                 else:
       
    97                     raise
       
    98 
    84         self.nesting_level -= 1
    99         self.nesting_level -= 1
    85         if models not in self.app_store:
   100         if models not in self.app_store:
    86             self.app_store[models] = len(self.app_store)
   101             self.app_store[models] = len(self.app_store)
    87         return models
   102         return models
    88 
   103 
   120                     if mod is None:
   135                     if mod is None:
   121                         if emptyOK:
   136                         if emptyOK:
   122                             return None
   137                             return None
   123                     else:
   138                     else:
   124                         return mod
   139                         return mod
   125             raise ImproperlyConfigured, "App with label %s could not be found" % app_label
   140             raise ImproperlyConfigured("App with label %s could not be found" % app_label)
   126         finally:
   141         finally:
   127             self.write_lock.release()
   142             self.write_lock.release()
   128 
   143 
   129     def get_app_errors(self):
   144     def get_app_errors(self):
   130         "Returns the map of known problems with the INSTALLED_APPS."
   145         "Returns the map of known problems with the INSTALLED_APPS."
   131         self._populate()
   146         self._populate()
   132         return self.app_errors
   147         return self.app_errors
   133 
   148 
   134     def get_models(self, app_mod=None):
   149     def get_models(self, app_mod=None, include_auto_created=False, include_deferred=False):
   135         """
   150         """
   136         Given a module containing models, returns a list of the models.
   151         Given a module containing models, returns a list of the models.
   137         Otherwise returns a list of all installed models.
   152         Otherwise returns a list of all installed models.
   138         """
   153 
       
   154         By default, auto-created models (i.e., m2m models without an
       
   155         explicit intermediate table) are not included. However, if you
       
   156         specify include_auto_created=True, they will be.
       
   157 
       
   158         By default, models created to satisfy deferred attribute
       
   159         queries are *not* included in the list of models. However, if
       
   160         you specify include_deferred, they will be.
       
   161         """
       
   162         cache_key = (app_mod, include_auto_created, include_deferred)
       
   163         try:
       
   164             return self._get_models_cache[cache_key]
       
   165         except KeyError:
       
   166             pass
   139         self._populate()
   167         self._populate()
   140         if app_mod:
   168         if app_mod:
   141             return self.app_models.get(app_mod.__name__.split('.')[-2], SortedDict()).values()
   169             app_list = [self.app_models.get(app_mod.__name__.split('.')[-2], SortedDict())]
   142         else:
   170         else:
   143             model_list = []
   171             app_list = self.app_models.itervalues()
   144             for app_entry in self.app_models.itervalues():
   172         model_list = []
   145                 model_list.extend(app_entry.values())
   173         for app in app_list:
   146             return model_list
   174             model_list.extend(
       
   175                 model for model in app.values()
       
   176                 if ((not model._deferred or include_deferred)
       
   177                     and (not model._meta.auto_created or include_auto_created))
       
   178             )
       
   179         self._get_models_cache[cache_key] = model_list
       
   180         return model_list
   147 
   181 
   148     def get_model(self, app_label, model_name, seed_cache=True):
   182     def get_model(self, app_label, model_name, seed_cache=True):
   149         """
   183         """
   150         Returns the model matching the given app_label and case-insensitive
   184         Returns the model matching the given app_label and case-insensitive
   151         model_name.
   185         model_name.
   175                 # .pyc or .pyo the second time, ignore the extension when
   209                 # .pyc or .pyo the second time, ignore the extension when
   176                 # comparing.
   210                 # comparing.
   177                 if os.path.splitext(fname1)[0] == os.path.splitext(fname2)[0]:
   211                 if os.path.splitext(fname1)[0] == os.path.splitext(fname2)[0]:
   178                     continue
   212                     continue
   179             model_dict[model_name] = model
   213             model_dict[model_name] = model
       
   214         self._get_models_cache.clear()
   180 
   215 
   181 cache = AppCache()
   216 cache = AppCache()
   182 
   217 
   183 # These methods were always module level, so are kept that way for backwards
   218 # These methods were always module level, so are kept that way for backwards
   184 # compatibility.
   219 # compatibility.