1
0
mirror of https://github.com/django/django.git synced 2025-04-22 16:24:40 +00:00

magic-removal: cleanup Options initialisation

git-svn-id: http://code.djangoproject.com/svn/django/branches/magic-removal@1728 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Robert Wittams 2005-12-18 21:07:17 +00:00
parent 5907e9337f
commit 743b02825e
2 changed files with 72 additions and 78 deletions

View File

@ -18,12 +18,7 @@ import sys
if not hasattr(__builtins__, 'set'):
from sets import Set as set
# Calculate the module_name using a poor-man's pluralization.
get_module_name = lambda class_name: class_name.lower() + 's'
# Calculate the verbose_name by converting from InitialCaps to "lowercase with spaces".
get_verbose_name = lambda class_name: re.sub('([A-Z])', ' \\1', class_name).lower().strip()
attribute_transforms = {}
class ModelBase(type):
"Metaclass for all models"
def __new__(cls, name, bases, attrs):
@ -31,69 +26,30 @@ class ModelBase(type):
if not bases or bases == (object,):
return type.__new__(cls, name, bases, attrs)
try:
meta_attrs = attrs.pop('META').__dict__
del meta_attrs['__module__']
del meta_attrs['__doc__']
except KeyError:
meta_attrs = {}
# Create the class.
new_class = type.__new__(cls, name, bases, {'__module__': attrs.pop('__module__')})
opts = Options(
module_name = meta_attrs.pop('module_name', get_module_name(name)),
# If the verbose_name wasn't given, use the class name,
# converted from "InitialCaps" to "lowercase with spaces".
verbose_name = meta_attrs.pop('verbose_name', get_verbose_name(name)),
verbose_name_plural = meta_attrs.pop('verbose_name_plural', ''),
db_table = meta_attrs.pop('db_table', ''),
ordering = meta_attrs.pop('ordering', None),
unique_together = meta_attrs.pop('unique_together', None),
admin = meta_attrs.pop('admin', None),
where_constraints = meta_attrs.pop('where_constraints', None),
object_name = name,
app_label = meta_attrs.pop('app_label', None),
exceptions = meta_attrs.pop('exceptions', None),
permissions = meta_attrs.pop('permissions', None),
get_latest_by = meta_attrs.pop('get_latest_by', None),
order_with_respect_to = meta_attrs.pop('order_with_respect_to', None),
module_constants = meta_attrs.pop('module_constants', None),
)
if meta_attrs != {}:
raise TypeError, "'class META' got invalid attribute(s): %s" % ','.join(meta_attrs.keys())
new_class.add_to_class('_meta', opts)
# Create the DoesNotExist exception.
new_class.DoesNotExist = types.ClassType('DoesNotExist', (ObjectDoesNotExist,), {})
# Figure out the app_label by looking one level up.
new_class.add_to_class('_meta',
Options(attrs.pop('META', None)))
new_class.add_to_class('DoesNotExist',
types.ClassType('DoesNotExist', (ObjectDoesNotExist,), {}) )
#Figure out the app_label by looking one level up.
#FIXME: wrong for nested model modules
app_package = sys.modules.get(new_class.__module__)
app_label = app_package.__name__.replace('.models', '')
app_label = app_label[app_label.rfind('.')+1:]
# Cache the app label.
opts.app_label = app_label
new_class._meta.app_label = app_label
# Add all attributes to the class.
for obj_name, obj in attrs.items():
new_class.add_to_class(obj_name, obj)
# Give the class a docstring -- its definition.
if new_class.__doc__ is None:
new_class.__doc__ = "%s.%s(%s)" % (opts.module_name, name, ", ".join([f.name for f in opts.fields]))
if hasattr(new_class, 'get_absolute_url'):
new_class.get_absolute_url = curry(get_absolute_url, opts, new_class.get_absolute_url)
opts._prepare()
new_class._prepare()
# Populate the _MODELS member on the module the class is in.
app_package.__dict__.setdefault('_MODELS', []).append(new_class)
return new_class
def cmp_cls(x, y):
@ -152,6 +108,9 @@ class Model(object):
dispatcher.send(signal=signals.post_init, sender=self.__class__, instance=self)
def add_to_class(cls, name, attribute):
transform = attribute_transforms.get(name, None)
if transform:
attribute = transform(attribute)
if hasattr(attribute, 'contribute_to_class'):
attribute.contribute_to_class(cls, name)
else:
@ -160,12 +119,21 @@ class Model(object):
def _prepare(cls):
# Creates some methods once self._meta has been populated.
if cls._meta.order_with_respect_to:
opts = cls._meta
opts._prepare()
if opts.order_with_respect_to:
cls.get_next_in_order = curry(cls._get_next_or_previous_in_order, is_next=True)
cls.get_previous_in_order = curry(cls._get_next_or_previous_in_order, is_next=False)
# Give the class a docstring -- its definition.
if cls.__doc__ is None:
cls.__doc__ = "%s.%s(%s)" % (opts.module_name, cls.__name__, ", ".join([f.name for f in opts.fields]))
if hasattr(cls, 'get_absolute_url'):
cls.get_absolute_url = curry(get_absolute_url, opts, cls.get_absolute_url)
dispatcher.send(signal=signals.class_prepared, sender=cls)
#RelatedField.do_pending_lookups(cls)
_prepare = classmethod(_prepare)

View File

@ -7,31 +7,56 @@ from django.db.models.exceptions import FieldDoesNotExist
from bisect import bisect
class Options:
def __init__(self, module_name='', verbose_name='', verbose_name_plural='', db_table='',
ordering=None, unique_together=None, admin=None,
where_constraints=None, object_name=None, app_label=None,
exceptions=None, permissions=None, get_latest_by=None,
order_with_respect_to=None, module_constants=None):
# Move many-to-many related fields from self.fields into self.many_to_many.
self.fields, self.many_to_many = [], []
self.module_name, self.verbose_name = module_name, verbose_name
self.verbose_name_plural = verbose_name_plural or verbose_name + 's'
self.db_table = db_table
self.ordering = ordering or []
self.unique_together = unique_together or []
self.where_constraints = where_constraints or []
self.exceptions = exceptions or []
self.permissions = permissions or []
self.object_name, self.app_label = object_name, app_label
self.get_latest_by = get_latest_by
self.order_with_respect_to = order_with_respect_to
self.module_constants = module_constants or {}
self.admin = admin
import re
# Calculate the module_name using a poor-man's pluralization.
get_module_name = lambda class_name: class_name.lower() + 's'
def contribute_to_class(self, cls, name):
# Calculate the verbose_name by converting from InitialCaps to "lowercase with spaces".
get_verbose_name = lambda class_name: re.sub('([A-Z])', ' \\1', class_name).lower().strip()
default_names = ['module_name','verbose_name','verbose_name_plural','db_table','ordering',
'unique_together', 'admin','where_constraints', 'exceptions', 'permissions',
'get_latest_by','order_with_respect_to', 'module_constants']
class Options:
def __init__(self, meta):
self.fields, self.many_to_many = [], []
self.module_name, self.verbose_name = None, None
self.verbose_name_plural = None
self.db_table = ''
self.ordering = []
self.unique_together = []
self.where_constraints = []
self.exceptions = []
self.permissions = []
self.object_name, self.app_label = None, None
self.get_latest_by = None
self.order_with_respect_to = None
self.module_constants = {}
self.admin = None
self.meta = meta
def merge_meta(self):
meta_attrs = self.meta.__dict__
del meta_attrs['__module__']
del meta_attrs['__doc__']
for attr_name in default_names:
setattr(self, attr_name, meta_attrs.pop(attr_name, getattr(self, attr_name)))
if meta_attrs != {}:
raise TypeError, "'class META' got invalid attribute(s): %s" % ','.join(meta_attrs.keys())
def contribute_to_class(self, cls, name):
self.model = cls
cls._meta = self
self.object_name = cls.__name__
self.module_name = get_module_name(self.object_name )
# If the verbose_name wasn't given, use the class name,
# converted from "InitialCaps" to "lowercase with spaces".
self.verbose_name = get_verbose_name(self.object_name)
self.verbose_name_plural = self.verbose_name + 's'
if self.meta:
self.merge_meta()
del self.meta
def _prepare(self):
if self.order_with_respect_to:
@ -77,6 +102,7 @@ class Options:
def add_field(self, field):
# Insert the given field in the order in which it was created, using
# the "creation_counter" attribute of the field.
# Move many-to-many related fields from self.fields into self.many_to_many.
if field.rel and isinstance(field.rel, ManyToMany):
self.many_to_many.insert(bisect(self.many_to_many, field), field)
else: