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:
parent
6f0861b256
commit
7aeeae67ee
|
@ -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 Field, DateField, FileField, ImageField, AutoField
|
||||||
from django.db.models.fields import OneToOne, ManyToOne, ManyToMany, RECURSIVE_RELATIONSHIP_CONSTANT
|
from django.db.models.fields import OneToOne, ManyToOne, ManyToMany, RECURSIVE_RELATIONSHIP_CONSTANT
|
||||||
from django.db.models.related import RelatedObject
|
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.query import orderlist2sql
|
||||||
from django.db.models.options import Options
|
from django.db.models.options import Options
|
||||||
from django.db import connection, backend
|
from django.db import connection, backend
|
||||||
|
@ -106,20 +106,14 @@ class ModelBase(type):
|
||||||
opts.db_table = "%s_%s" % (app_label, opts.module_name)
|
opts.db_table = "%s_%s" % (app_label, opts.module_name)
|
||||||
new_class._meta = opts
|
new_class._meta = opts
|
||||||
|
|
||||||
# Create the default manager, if needed.
|
for m_name, m in managers:
|
||||||
# TODO: Use weakref because of possible memory leak / circular reference.
|
new_class.add_to_class(m_name, m)
|
||||||
if managers:
|
|
||||||
for m_name, m in managers:
|
if not hasattr(new_class, '_default_manager'):
|
||||||
m._prepare(new_class)
|
# Create the default manager, if needed.
|
||||||
setattr(new_class, m_name, m)
|
|
||||||
new_class._default_manager = managers[0][1]
|
|
||||||
else:
|
|
||||||
if hasattr(new_class, 'objects'):
|
if hasattr(new_class, 'objects'):
|
||||||
raise ValueError, "Model %s must specify a custom Manager, because it has a field named 'objects'" % name
|
raise ValueError, "Model %s must specify a custom Manager, because it has a field named 'objects'" % name
|
||||||
m = Manager()
|
new_class.add_to_class('objects', Manager())
|
||||||
m._prepare(new_class)
|
|
||||||
new_class.objects = m
|
|
||||||
new_class._default_manager = m
|
|
||||||
|
|
||||||
new_class._prepare()
|
new_class._prepare()
|
||||||
|
|
||||||
|
@ -139,6 +133,13 @@ class ModelBase(type):
|
||||||
class Model(object):
|
class Model(object):
|
||||||
__metaclass__ = ModelBase
|
__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)
|
AddManipulator = ManipulatorDescriptor('AddManipulator', ModelAddManipulator)
|
||||||
ChangeManipulator = ManipulatorDescriptor('ChangeManipulator', ModelChangeManipulator)
|
ChangeManipulator = ManipulatorDescriptor('ChangeManipulator', ModelChangeManipulator)
|
||||||
|
|
||||||
|
|
|
@ -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.
|
# Larger values are slightly faster at the expense of more storage space.
|
||||||
GET_ITERATOR_CHUNK_SIZE = 100
|
GET_ITERATOR_CHUNK_SIZE = 100
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class Manager(object):
|
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
|
creation_counter = 0
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
# Increase the creation counter, and save our local copy.
|
# Increase the creation counter, and save our local copy.
|
||||||
self.creation_counter = Manager.creation_counter
|
self.creation_counter = Manager.creation_counter
|
||||||
Manager.creation_counter += 1
|
Manager.creation_counter += 1
|
||||||
|
self.klass = None
|
||||||
def __get__(self, instance, type=None):
|
|
||||||
if instance != None:
|
|
||||||
raise AttributeError, "Manager isn't accessible via %s instances" % self.klass.__name__
|
|
||||||
return self
|
|
||||||
|
|
||||||
def _prepare(self, klass):
|
def _prepare(self, klass):
|
||||||
# Creates some methods once self.klass._meta has been populated.
|
|
||||||
self.klass = klass
|
self.klass = klass
|
||||||
if self.klass._meta.get_latest_by:
|
if self.klass._meta.get_latest_by:
|
||||||
self.get_latest = self.__get_latest
|
self.get_latest = self.__get_latest
|
||||||
|
@ -34,6 +26,14 @@ class Manager(object):
|
||||||
if isinstance(f, DateField):
|
if isinstance(f, DateField):
|
||||||
setattr(self, 'get_%s_list' % f.name, curry(self.__get_date_list, f))
|
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 _get_sql_clause(self, **kwargs):
|
||||||
def quote_only_if_word(word):
|
def quote_only_if_word(word):
|
||||||
if ' ' in word:
|
if ' ' in word:
|
||||||
|
@ -204,4 +204,13 @@ class Manager(object):
|
||||||
# We have to manually run typecast_timestamp(str()) on the results, because
|
# We have to manually run typecast_timestamp(str()) on the results, because
|
||||||
# MySQL doesn't automatically cast the result of date functions as datetime
|
# MySQL doesn't automatically cast the result of date functions as datetime
|
||||||
# objects -- MySQL returns the values as strings, instead.
|
# 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
|
Loading…
Reference in New Issue