Seperate managers from their descriptors.

git-svn-id: http://code.djangoproject.com/svn/django/branches/magic-removal@1697 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Robert Wittams 2005-12-16 15:14:12 +00:00
parent 6f0861b256
commit 7aeeae67ee
2 changed files with 35 additions and 25 deletions

View File

@ -2,7 +2,7 @@ from django.db.models.manipulators import ManipulatorDescriptor, ModelAddManipul
from django.db.models.fields import Field, DateField, FileField, ImageField, AutoField
from django.db.models.fields import OneToOne, ManyToOne, ManyToMany, RECURSIVE_RELATIONSHIP_CONSTANT
from django.db.models.related import RelatedObject
from django.db.models.manager import Manager
from django.db.models.manager import Manager, ManagerDescriptor
from django.db.models.query import orderlist2sql
from django.db.models.options import Options
from django.db import connection, backend
@ -106,20 +106,14 @@ class ModelBase(type):
opts.db_table = "%s_%s" % (app_label, opts.module_name)
new_class._meta = opts
# Create the default manager, if needed.
# TODO: Use weakref because of possible memory leak / circular reference.
if managers:
for m_name, m in managers:
m._prepare(new_class)
setattr(new_class, m_name, m)
new_class._default_manager = managers[0][1]
else:
for m_name, m in managers:
new_class.add_to_class(m_name, m)
if not hasattr(new_class, '_default_manager'):
# Create the default manager, if needed.
if hasattr(new_class, 'objects'):
raise ValueError, "Model %s must specify a custom Manager, because it has a field named 'objects'" % name
m = Manager()
m._prepare(new_class)
new_class.objects = m
new_class._default_manager = m
new_class.add_to_class('objects', Manager())
new_class._prepare()
@ -139,6 +133,13 @@ class ModelBase(type):
class Model(object):
__metaclass__ = ModelBase
def add_to_class(cls, name, attribute):
if hasattr(attribute, 'contribute_to_class'):
attribute.contribute_to_class(cls, name)
else:
setattr(cls, name, attribute)
add_to_class = classmethod(add_to_class)
AddManipulator = ManipulatorDescriptor('AddManipulator', ModelAddManipulator)
ChangeManipulator = ManipulatorDescriptor('ChangeManipulator', ModelChangeManipulator)

View File

@ -8,25 +8,17 @@ from django.db.models.query import handle_legacy_orderlist, orderlist2sql, order
# Larger values are slightly faster at the expense of more storage space.
GET_ITERATOR_CHUNK_SIZE = 100
class Manager(object):
# Tracks each time a Field instance is created. Used to retain order.
# Tracks each time a Field instance is created. Used to retain order.
creation_counter = 0
def __init__(self):
# Increase the creation counter, and save our local copy.
self.creation_counter = Manager.creation_counter
Manager.creation_counter += 1
def __get__(self, instance, type=None):
if instance != None:
raise AttributeError, "Manager isn't accessible via %s instances" % self.klass.__name__
return self
self.klass = None
def _prepare(self, klass):
# Creates some methods once self.klass._meta has been populated.
self.klass = klass
if self.klass._meta.get_latest_by:
self.get_latest = self.__get_latest
@ -34,6 +26,14 @@ class Manager(object):
if isinstance(f, DateField):
setattr(self, 'get_%s_list' % f.name, curry(self.__get_date_list, f))
def contribute_to_class(self, klass, name):
# TODO: Use weakref because of possible memory leak / circular reference.
self._prepare(klass)
setattr(klass,name, ManagerDescriptor(self))
if not hasattr(klass, '_default_manager') or \
self.creation_counter < klass._default_manager.creation_counter:
klass._default_manager = self
def _get_sql_clause(self, **kwargs):
def quote_only_if_word(word):
if ' ' in word:
@ -204,4 +204,13 @@ class Manager(object):
# We have to manually run typecast_timestamp(str()) on the results, because
# MySQL doesn't automatically cast the result of date functions as datetime
# objects -- MySQL returns the values as strings, instead.
return [typecast_timestamp(str(row[0])) for row in cursor.fetchall()]
return [typecast_timestamp(str(row[0])) for row in cursor.fetchall()]
class ManagerDescriptor(object):
def __init__(self, manager):
self.manager = manager
def __get__(self, instance, type=None):
if instance != None:
raise AttributeError, "Manager isn't accessible via %s instances" % type.__name__
return self.manager