magic-removal: Refactored get_installed_models and get_installed_model_modules to get_apps, get_app, get_models and get_model

git-svn-id: http://code.djangoproject.com/svn/django/branches/magic-removal@2106 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Adrian Holovaty 2006-01-23 02:29:34 +00:00
parent 17ece1adb8
commit 25e1e1392f
7 changed files with 166 additions and 178 deletions

View File

@ -1,4 +1,5 @@
from django import template
from django.db.models import get_models
register = template.Library()
@ -12,13 +13,18 @@ class AdminApplistNode(template.Node):
app_list = []
user = context['user']
for app in models.get_installed_model_modules():
app_label = app.__name__.split('.')[-2] # TODO: Abstract this logic
for app in models.get_apps():
# Determine the app_label.
app_models = get_models(app)
if not app_models:
continue
app_label = app_models[0]._meta.app_label
has_module_perms = user.has_module_perms(app_label)
if has_module_perms:
model_list = []
for m in app._MODELS:
for m in app_models:
if m._meta.admin:
perms = {
'add': user.has_perm("%s.%s" % (app_label, m._meta.get_add_permission())),

View File

@ -137,10 +137,7 @@ def model_index(request):
if not utils.docutils_is_available:
return missing_docutils_page(request)
m_list = []
for app in models.get_installed_model_modules():
for model in app._MODELS:
m_list.append(model._meta)
m_list = [m._meta for m in models.get_models()]
return render_to_response('admin_doc/model_index', {'models': m_list}, context_instance=RequestContext(request))
model_index = staff_member_required(model_index)

View File

@ -41,14 +41,6 @@ use_raw_id_admin = lambda field: isinstance(field.rel, (models.ManyToOne, models
class IncorrectLookupParameters(Exception):
pass
def get_model(app_label, model_name):
for module in models.get_installed_models():
if module.__name__.split('.')[-2] == app_label: # TODO: Refactor this logic.
for model in getattr(module, '_MODELS', ()):
if model._meta.object_name.lower() == model_name:
return model
raise Http404, "App %r, model %r, not found" % (app_label, model_name)
def get_javascript_imports(opts, auto_populated_fields, field_sets):
# Put in any necessary JavaScript imports.
js = ['js/core.js', 'js/admin/RelatedObjectLookups.js']
@ -192,7 +184,9 @@ def index(request):
index = staff_member_required(index)
def add_stage(request, app_label, model_name, show_delete=False, form_url='', post_url='../', post_url_continue='../%s/', object_id_override=None):
model = get_model(app_label, model_name)
model = models.get_model(app_label, model_name)
if model is None:
raise Http404, "App %r, model %r, not found" % (app_label, model_name)
opts = model._meta
if not request.user.has_perm(app_label + '.' + opts.get_add_permission()):
@ -255,7 +249,9 @@ def add_stage(request, app_label, model_name, show_delete=False, form_url='', po
add_stage = staff_member_required(add_stage)
def change_stage(request, app_label, model_name, object_id):
model = get_model(app_label, model_name)
model = models.get_model(app_label, model_name)
if model is None:
raise Http404, "App %r, model %r, not found" % (app_label, model_name)
opts = model._meta
if not request.user.has_perm(app_label + '.' + opts.get_change_permission()):
@ -436,7 +432,9 @@ def _get_deleted_objects(deleted_objects, perms_needed, user, obj, opts, current
def delete_stage(request, app_label, model_name, object_id):
import sets
model = get_model(app_label, model_name)
model = models.get_model(app_label, model_name)
if model is None:
raise Http404, "App %r, model %r, not found" % (app_label, model_name)
opts = model._meta
if not request.user.has_perm(app_label + '.' + opts.get_delete_permission()):
raise PermissionDenied
@ -466,7 +464,9 @@ def delete_stage(request, app_label, model_name, object_id):
delete_stage = staff_member_required(delete_stage)
def history(request, app_label, model_name, object_id):
model = get_model(app_label, model_name)
model = models.get_model(app_label, model_name)
if model is None:
raise Http404, "App %r, model %r, not found" % (app_label, model_name)
action_list = LogEntry.objects.get_list(object_id__exact=object_id, content_type__id__exact=model._meta.get_content_type_id(),
order_by=("action_time",), select_related=True)
# If no history was found, see whether this object even exists.
@ -651,7 +651,9 @@ class ChangeList(object):
self.lookup_params = lookup_params
def change_list(request, app_label, model_name):
model = get_model(app_label, model_name)
model = models.get_model(app_label, model_name)
if model is None:
raise Http404, "App %r, model %r, not found" % (app_label, model_name)
if not request.user.has_perm(app_label + '.' + model._meta.get_change_permission()):
raise PermissionDenied
try:

View File

@ -767,101 +767,99 @@ def get_validation_errors(outfile):
"Validates all installed models. Writes errors, if any, to outfile. Returns number of errors."
from django.db import models
e = ModelErrorCollection(outfile)
module_list = models.get_installed_model_modules()
for module in module_list:
for cls in module._MODELS:
opts = cls._meta
for cls in models.get_models():
opts = cls._meta
# Do field-specific validation.
for f in opts.fields:
# Check for deprecated args
dep_args = getattr(f, 'deprecated_args', None)
if dep_args:
e.add(opts, "'%s' field: Initialised with deprecated args:%s" % (f.name, ",".join(dep_args)))
if isinstance(f, models.CharField) and f.maxlength in (None, 0):
e.add(opts, '"%s" field: CharFields require a "maxlength" attribute.' % f.name)
if isinstance(f, models.FloatField):
if f.decimal_places is None:
e.add(opts, '"%s" field: FloatFields require a "decimal_places" attribute.' % f.name)
if f.max_digits is None:
e.add(opts, '"%s" field: FloatFields require a "max_digits" attribute.' % f.name)
if isinstance(f, models.FileField) and not f.upload_to:
e.add(opts, '"%s" field: FileFields require an "upload_to" attribute.' % f.name)
if isinstance(f, models.ImageField):
try:
from PIL import Image
except ImportError:
e.add(opts, '"%s" field: To use ImageFields, you need to install the Python Imaging Library. Get it at http://www.pythonware.com/products/pil/ .' % f.name)
if f.prepopulate_from is not None and type(f.prepopulate_from) not in (list, tuple):
e.add(opts, '"%s" field: prepopulate_from should be a list or tuple.' % f.name)
if f.choices:
if not type(f.choices) in (tuple, list):
e.add(opts, '"%s" field: "choices" should be either a tuple or list.' % f.name)
else:
for c in f.choices:
if not type(c) in (tuple, list) or len(c) != 2:
e.add(opts, '"%s" field: "choices" should be a sequence of two-tuples.' % f.name)
if f.db_index not in (None, True, False):
e.add(opts, '"%s" field: "db_index" should be either None, True or False.' % f.name)
# Check for multiple ManyToManyFields to the same object, and
# verify "singular" is set in that case.
for i, f in enumerate(opts.many_to_many):
for previous_f in opts.many_to_many[:i]:
if f.rel.to._meta == previous_f.rel.to._meta and f.rel.singular == previous_f.rel.singular:
e.add(opts, 'The "%s" field requires a "singular" parameter, because the %s model has more than one ManyToManyField to the same model (%s).' % (f.name, opts.object_name, previous_f.rel.to._meta.object_name))
# Check admin attribute.
if opts.admin is not None:
if not isinstance(opts.admin, models.AdminOptions):
e.add(opts, '"admin" attribute, if given, must be set to a models.AdminOptions() instance.')
# Do field-specific validation.
for f in opts.fields:
# Check for deprecated args
dep_args = getattr(f, 'deprecated_args', None)
if dep_args:
e.add(opts, "'%s' field: Initialised with deprecated args:%s" % (f.name, ",".join(dep_args)))
if isinstance(f, models.CharField) and f.maxlength in (None, 0):
e.add(opts, '"%s" field: CharFields require a "maxlength" attribute.' % f.name)
if isinstance(f, models.FloatField):
if f.decimal_places is None:
e.add(opts, '"%s" field: FloatFields require a "decimal_places" attribute.' % f.name)
if f.max_digits is None:
e.add(opts, '"%s" field: FloatFields require a "max_digits" attribute.' % f.name)
if isinstance(f, models.FileField) and not f.upload_to:
e.add(opts, '"%s" field: FileFields require an "upload_to" attribute.' % f.name)
if isinstance(f, models.ImageField):
try:
from PIL import Image
except ImportError:
e.add(opts, '"%s" field: To use ImageFields, you need to install the Python Imaging Library. Get it at http://www.pythonware.com/products/pil/ .' % f.name)
if f.prepopulate_from is not None and type(f.prepopulate_from) not in (list, tuple):
e.add(opts, '"%s" field: prepopulate_from should be a list or tuple.' % f.name)
if f.choices:
if not type(f.choices) in (tuple, list):
e.add(opts, '"%s" field: "choices" should be either a tuple or list.' % f.name)
else:
# list_display
if not isinstance(opts.admin.list_display, (list, tuple)):
e.add(opts, '"admin.list_display", if given, must be set to a list or tuple.')
else:
for fn in opts.admin.list_display:
try:
f = opts.get_field(fn)
except models.FieldDoesNotExist:
if not hasattr(cls, fn) or not callable(getattr(cls, fn)):
e.add(opts, '"admin.list_display" refers to %r, which isn\'t a field or method.' % fn)
else:
if isinstance(f, models.ManyToManyField):
e.add(opts, '"admin.list_display" doesn\'t support ManyToManyFields (%r).' % fn)
# list_filter
if not isinstance(opts.admin.list_filter, (list, tuple)):
e.add(opts, '"admin.list_filter", if given, must be set to a list or tuple.')
else:
for fn in opts.admin.list_filter:
try:
f = opts.get_field(fn)
except models.FieldDoesNotExist:
e.add(opts, '"admin.list_filter" refers to %r, which isn\'t a field.' % fn)
for c in f.choices:
if not type(c) in (tuple, list) or len(c) != 2:
e.add(opts, '"%s" field: "choices" should be a sequence of two-tuples.' % f.name)
if f.db_index not in (None, True, False):
e.add(opts, '"%s" field: "db_index" should be either None, True or False.' % f.name)
# Check ordering attribute.
if opts.ordering:
for field_name in opts.ordering:
if field_name == '?': continue
if field_name.startswith('-'):
field_name = field_name[1:]
if opts.order_with_respect_to and field_name == '_order':
continue
try:
opts.get_field(field_name, many_to_many=False)
except models.FieldDoesNotExist:
e.add(opts, '"ordering" refers to "%s", a field that doesn\'t exist.' % field_name)
# Check for multiple ManyToManyFields to the same object, and
# verify "singular" is set in that case.
for i, f in enumerate(opts.many_to_many):
for previous_f in opts.many_to_many[:i]:
if f.rel.to._meta == previous_f.rel.to._meta and f.rel.singular == previous_f.rel.singular:
e.add(opts, 'The "%s" field requires a "singular" parameter, because the %s model has more than one ManyToManyField to the same model (%s).' % (f.name, opts.object_name, previous_f.rel.to._meta.object_name))
# Check unique_together.
for ut in opts.unique_together:
for field_name in ut:
try:
f = opts.get_field(field_name, many_to_many=True)
except models.FieldDoesNotExist:
e.add(opts, '"unique_together" refers to %s, a field that doesn\'t exist. Check your syntax.' % field_name)
else:
if isinstance(f.rel, models.ManyToMany):
e.add(opts, '"unique_together" refers to %s. ManyToManyFields are not supported in unique_together.' % f.name)
# Check admin attribute.
if opts.admin is not None:
if not isinstance(opts.admin, models.AdminOptions):
e.add(opts, '"admin" attribute, if given, must be set to a models.AdminOptions() instance.')
else:
# list_display
if not isinstance(opts.admin.list_display, (list, tuple)):
e.add(opts, '"admin.list_display", if given, must be set to a list or tuple.')
else:
for fn in opts.admin.list_display:
try:
f = opts.get_field(fn)
except models.FieldDoesNotExist:
if not hasattr(cls, fn) or not callable(getattr(cls, fn)):
e.add(opts, '"admin.list_display" refers to %r, which isn\'t a field or method.' % fn)
else:
if isinstance(f, models.ManyToManyField):
e.add(opts, '"admin.list_display" doesn\'t support ManyToManyFields (%r).' % fn)
# list_filter
if not isinstance(opts.admin.list_filter, (list, tuple)):
e.add(opts, '"admin.list_filter", if given, must be set to a list or tuple.')
else:
for fn in opts.admin.list_filter:
try:
f = opts.get_field(fn)
except models.FieldDoesNotExist:
e.add(opts, '"admin.list_filter" refers to %r, which isn\'t a field.' % fn)
# Check ordering attribute.
if opts.ordering:
for field_name in opts.ordering:
if field_name == '?': continue
if field_name.startswith('-'):
field_name = field_name[1:]
if opts.order_with_respect_to and field_name == '_order':
continue
try:
opts.get_field(field_name, many_to_many=False)
except models.FieldDoesNotExist:
e.add(opts, '"ordering" refers to "%s", a field that doesn\'t exist.' % field_name)
# Check unique_together.
for ut in opts.unique_together:
for field_name in ut:
try:
f = opts.get_field(field_name, many_to_many=True)
except models.FieldDoesNotExist:
e.add(opts, '"unique_together" refers to %s, a field that doesn\'t exist. Check your syntax.' % field_name)
else:
if isinstance(f.rel, models.ManyToMany):
e.add(opts, '"unique_together" refers to %s. ManyToManyFields are not supported in unique_together.' % f.name)
return len(e.errors)

View File

@ -2,7 +2,7 @@ from django.conf import settings
from django.core.exceptions import ObjectDoesNotExist, ImproperlyConfigured
from django.core import validators
from django.db import backend, connection
from django.db.models.loading import get_installed_models, get_installed_model_modules
from django.db.models.loading import *
from django.db.models.query import Q
from django.db.models.manager import Manager
from django.db.models.base import Model, AdminOptions
@ -16,27 +16,6 @@ from django.utils.text import capfirst
# Admin stages.
ADD, CHANGE, BOTH = 1, 2, 3
def get_models(app):
models = []
get_models_helper(app, models)
return models
def get_models_helper(mod, seen_models):
if hasattr(mod, '_MODELS'):
seen_models.extend(mod._MODELS)
if hasattr(mod, '__all__'):
for name in mod.__all__:
sub_mod = __import__("%s.%s" % (mod.__name__, name), '', '', [''])
get_models_helper(sub_mod, seen_models)
def get_app(app_label):
for app_name in settings.INSTALLED_APPS:
comps = app_name.split('.')
if app_label == comps[-1]:
app_models = __import__('%s.models' % app_name, '', '', [''])
return app_models
raise ImproperlyConfigured, "App with label %s could not be found" % app_label
class LazyDate:
"""
Use in limit_choices_to to compare the field to dates calculated at run time

View File

@ -1,40 +1,50 @@
from django.conf import settings
_installed_models_cache = None
"Utilities for loading models and the modules that contain them."
def get_installed_models():
"""
Returns a list of installed "models" packages, such as foo.models,
ellington.news.models, etc. This does NOT include django.models.
"""
global _installed_models_cache
if _installed_models_cache is not None:
return _installed_models_cache
_installed_models_cache = []
for a in settings.INSTALLED_APPS:
from django.conf import settings
__all__ = ('get_apps', 'get_app', 'get_models', 'get_model')
_app_list = None # Cache of installed apps.
def get_apps():
"Returns a list of all installed modules that contain models."
global _app_list
if _app_list is not None:
return _app_list
_app_list = []
for app_name in settings.INSTALLED_APPS:
try:
_installed_models_cache.append(__import__(a + '.models', '', '', ['']))
_app_list.append(__import__(app_name + '.models', '', '', ['']))
except ImportError, e:
pass
return _installed_models_cache
return _app_list
_installed_modules_cache = None
def get_app(app_label):
"Returns the module containing the models for the given app_label."
for app_name in settings.INSTALLED_APPS:
if app_label == app_name.split('.')[-1]:
return __import__('%s.models' % app_name, '', '', [''])
raise ImproperlyConfigured, "App with label %s could not be found" % app_label
def add_model_module(mod, modules):
if hasattr(mod, '_MODELS'):
modules.append(mod)
for name in getattr(mod, '__all__', []):
submod = __import__("%s.%s" % (mod.__name__, name), '', '', [''])
add_model_module(submod, modules)
def get_installed_model_modules():
def get_models(app_mod=None):
"""
Returns a list of installed models, such as django.models.core,
ellington.news.models.news, foo.models.bar, etc.
Given a module containing models, returns a list of the models. Otherwise
returns a list of all installed models.
"""
global _installed_modules_cache
if _installed_modules_cache is not None:
return _installed_modules_cache
_installed_modules_cache = []
for mod in get_installed_models():
add_model_module(mod, _installed_modules_cache)
return _installed_modules_cache
if app_mod:
return getattr(app_mod, '_MODELS', ())
else:
model_list = []
for app_mod in get_apps():
model_list.extend(getattr(app_mod, '_MODELS', ()))
return model_list
def get_model(app_label, model_name):
"""
Returns the model matching the given app_label and case-insensitive model_name.
Returns None if no model is found.
"""
for app_mod in get_apps():
for model in get_models(app_mod):
if model._meta.object_name.lower() == model_name:
return model

View File

@ -1,7 +1,7 @@
from django.db.models.related import RelatedObject
from django.db.models.fields.related import ManyToMany
from django.db.models.fields import AutoField
from django.db.models.loading import get_installed_model_modules
from django.db.models.loading import get_models
from django.db.models.query import orderlist2sql
from django.db.models.exceptions import FieldDoesNotExist
from bisect import bisect
@ -127,13 +127,11 @@ class Options:
try: # Try the cache first.
return self._all_related_objects
except AttributeError:
module_list = get_installed_model_modules()
rel_objs = []
for mod in module_list:
for klass in mod._MODELS:
for f in klass._meta.fields:
if f.rel and self == f.rel.to._meta:
rel_objs.append(RelatedObject(self, klass, f))
for klass in get_models():
for f in klass._meta.fields:
if f.rel and self == f.rel.to._meta:
rel_objs.append(RelatedObject(self, klass, f))
self._all_related_objects = rel_objs
return rel_objs
@ -163,13 +161,11 @@ class Options:
try: # Try the cache first.
return self._all_related_many_to_many_objects
except AttributeError:
module_list = get_installed_model_modules()
rel_objs = []
for mod in module_list:
for klass in mod._MODELS:
for f in klass._meta.many_to_many:
if f.rel and self == f.rel.to._meta:
rel_objs.append(RelatedObject(self, klass, f))
for klass in get_models():
for f in klass._meta.many_to_many:
if f.rel and self == f.rel.to._meta:
rel_objs.append(RelatedObject(self, klass, f))
self._all_related_many_to_many_objects = rel_objs
return rel_objs