Ensure swapped models can't be queried.

This commit is contained in:
Russell Keith-Magee 2012-09-15 19:59:49 +08:00
parent 57ac6e3d32
commit 5d7bb22e8d
2 changed files with 15 additions and 5 deletions

View File

@ -13,7 +13,7 @@ def ensure_default_manager(sender, **kwargs):
_default_manager if it's not a subclass of Manager).
"""
cls = sender
if cls._meta.abstract:
if cls._meta.abstract or cls._meta.swapped:
return
if not getattr(cls, '_default_manager', None):
# Create the default manager, if needed.
@ -42,6 +42,7 @@ def ensure_default_manager(sender, **kwargs):
signals.class_prepared.connect(ensure_default_manager)
class Manager(object):
# Tracks each time a Manager instance is created. Used to retain order.
creation_counter = 0
@ -56,7 +57,9 @@ class Manager(object):
def contribute_to_class(self, model, name):
# TODO: Use weakref because of possible memory leak / circular reference.
self.model = model
setattr(model, name, ManagerDescriptor(self))
# Only contribute the manager if the model is concrete
if not model._meta.abstract and not model._meta.swapped:
setattr(model, name, ManagerDescriptor(self))
if not getattr(model, '_default_manager', None) or self.creation_counter < model._default_manager.creation_counter:
model._default_manager = self
if model._meta.abstract or (self._inherited and not self.model._meta.proxy):
@ -208,6 +211,7 @@ class Manager(object):
def raw(self, raw_query, params=None, *args, **kwargs):
return RawQuerySet(raw_query=raw_query, model=self.model, params=params, using=self._db, *args, **kwargs)
class ManagerDescriptor(object):
# This class ensures managers aren't accessible via model instances.
# For example, Poll.objects works, but poll_obj.objects raises AttributeError.
@ -219,6 +223,7 @@ class ManagerDescriptor(object):
raise AttributeError("Manager isn't accessible via %s instances" % type.__name__)
return self.manager
class EmptyManager(Manager):
def get_query_set(self):
return self.get_empty_query_set()

View File

@ -222,10 +222,15 @@ class Options(object):
def _swapped(self):
"""
Has this model been swapped out for another?
Has this model been swapped out for another? If so, return the model
name of the replacement; otherwise, return None.
"""
model_label = '%s.%s' % (self.app_label, self.object_name)
return self.swappable and getattr(settings, self.swappable, None) not in (None, model_label)
if self.swappable:
model_label = '%s.%s' % (self.app_label, self.object_name)
swapped_for = getattr(settings, self.swappable, None)
if swapped_for not in (None, model_label):
return swapped_for
return None
swapped = property(_swapped)
def _fields(self):