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 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)
|
||||
|
||||
|
|
|
@ -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
|
Loading…
Reference in New Issue