PEP 8 cleaning
Conflicts: polymorphic/__init__.py polymorphic/polymorphic_model.pyfix_request_path_info
parent
c9922d8987
commit
f987818fe4
|
|
@ -6,16 +6,16 @@ Copyright:
|
||||||
This code and affiliated files are (C) by Bert Constantin and individual contributors.
|
This code and affiliated files are (C) by Bert Constantin and individual contributors.
|
||||||
Please see LICENSE and AUTHORS for more information.
|
Please see LICENSE and AUTHORS for more information.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from polymorphic_model import PolymorphicModel
|
from polymorphic_model import PolymorphicModel
|
||||||
from manager import PolymorphicManager
|
from manager import PolymorphicManager
|
||||||
from query import PolymorphicQuerySet
|
from query import PolymorphicQuerySet
|
||||||
from query_translate import translate_polymorphic_Q_object
|
from query_translate import translate_polymorphic_Q_object
|
||||||
from showfields import ShowFieldContent, ShowFieldType, ShowFieldTypeAndContent
|
from showfields import ShowFieldContent, ShowFieldType, ShowFieldTypeAndContent
|
||||||
from showfields import ShowFields, ShowFieldTypes, ShowFieldsAndTypes # import old names for compatibility
|
from showfields import ShowFields, ShowFieldTypes, ShowFieldsAndTypes # import old names for compatibility
|
||||||
|
|
||||||
|
|
||||||
VERSION = (1, 0 , 0, 'beta')
|
VERSION = (1, 0, 0, 'beta')
|
||||||
|
|
||||||
|
|
||||||
def get_version():
|
def get_version():
|
||||||
version = '%s.%s' % VERSION[0:2]
|
version = '%s.%s' % VERSION[0:2]
|
||||||
|
|
@ -23,4 +23,35 @@ def get_version():
|
||||||
version += '.%s' % VERSION[2]
|
version += '.%s' % VERSION[2]
|
||||||
if VERSION[3]:
|
if VERSION[3]:
|
||||||
version += ' %s' % VERSION[3]
|
version += ' %s' % VERSION[3]
|
||||||
return version
|
return version
|
||||||
|
|
||||||
|
|
||||||
|
# Proxied models need to have it's own ContentType
|
||||||
|
|
||||||
|
|
||||||
|
from django.contrib.contenttypes.models import ContentTypeManager
|
||||||
|
from django.utils.encoding import smart_unicode
|
||||||
|
|
||||||
|
|
||||||
|
def get_for_proxied_model(self, model):
|
||||||
|
"""
|
||||||
|
Returns the ContentType object for a given model, creating the
|
||||||
|
ContentType if necessary. Lookups are cached so that subsequent lookups
|
||||||
|
for the same model don't hit the database.
|
||||||
|
"""
|
||||||
|
opts = model._meta
|
||||||
|
key = (opts.app_label, opts.object_name.lower())
|
||||||
|
try:
|
||||||
|
ct = self.__class__._cache[self.db][key]
|
||||||
|
except KeyError:
|
||||||
|
# Load or create the ContentType entry. The smart_unicode() is
|
||||||
|
# needed around opts.verbose_name_raw because name_raw might be a
|
||||||
|
# django.utils.functional.__proxy__ object.
|
||||||
|
ct, created = self.get_or_create(
|
||||||
|
app_label=opts.app_label,
|
||||||
|
model=opts.object_name.lower(),
|
||||||
|
defaults={'name': smart_unicode(opts.verbose_name_raw)},
|
||||||
|
)
|
||||||
|
self._add_to_cache(self.db, ct)
|
||||||
|
return ct
|
||||||
|
ContentTypeManager.get_for_proxied_model = get_for_proxied_model
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ from query import PolymorphicQuerySet
|
||||||
|
|
||||||
# PolymorphicQuerySet Q objects (and filter()) support these additional key words.
|
# PolymorphicQuerySet Q objects (and filter()) support these additional key words.
|
||||||
# These are forbidden as field names (a descriptive exception is raised)
|
# These are forbidden as field names (a descriptive exception is raised)
|
||||||
POLYMORPHIC_SPECIAL_Q_KWORDS = [ 'instance_of', 'not_instance_of']
|
POLYMORPHIC_SPECIAL_Q_KWORDS = ['instance_of', 'not_instance_of']
|
||||||
|
|
||||||
|
|
||||||
###################################################################################
|
###################################################################################
|
||||||
|
|
@ -79,8 +79,8 @@ class PolymorphicModelBase(ModelBase):
|
||||||
# determine the name of the primary key field and store it into the class variable
|
# determine the name of the primary key field and store it into the class variable
|
||||||
# polymorphic_primary_key_name (it is needed by query.py)
|
# polymorphic_primary_key_name (it is needed by query.py)
|
||||||
for f in new_class._meta.fields:
|
for f in new_class._meta.fields:
|
||||||
if f.primary_key and type(f)!=models.OneToOneField:
|
if f.primary_key and type(f) != models.OneToOneField:
|
||||||
new_class.polymorphic_primary_key_name=f.name
|
new_class.polymorphic_primary_key_name = f.name
|
||||||
break
|
break
|
||||||
|
|
||||||
return new_class
|
return new_class
|
||||||
|
|
@ -97,7 +97,7 @@ class PolymorphicModelBase(ModelBase):
|
||||||
if not issubclass(base, models.Model):
|
if not issubclass(base, models.Model):
|
||||||
continue
|
continue
|
||||||
if not getattr(base, 'polymorphic_model_marker', None):
|
if not getattr(base, 'polymorphic_model_marker', None):
|
||||||
continue # leave managers of non-polym. models alone
|
continue # leave managers of non-polym. models alone
|
||||||
|
|
||||||
for key, manager in base.__dict__.items():
|
for key, manager in base.__dict__.items():
|
||||||
if type(manager) == models.manager.ManagerDescriptor:
|
if type(manager) == models.manager.ManagerDescriptor:
|
||||||
|
|
@ -113,7 +113,7 @@ class PolymorphicModelBase(ModelBase):
|
||||||
if manager._inherited:
|
if manager._inherited:
|
||||||
continue # inherited managers (on the bases) have no significance, they are just copies
|
continue # inherited managers (on the bases) have no significance, they are just copies
|
||||||
#print >>sys.stderr,'##',self.__name__, key
|
#print >>sys.stderr,'##',self.__name__, key
|
||||||
if isinstance(manager, PolymorphicManager): # validate any inherited polymorphic managers
|
if isinstance(manager, PolymorphicManager): # validate any inherited polymorphic managers
|
||||||
self.validate_model_manager(manager, self.__name__, key)
|
self.validate_model_manager(manager, self.__name__, key)
|
||||||
add_managers.append((base.__name__, key, manager))
|
add_managers.append((base.__name__, key, manager))
|
||||||
add_managers_keys.add(key)
|
add_managers_keys.add(key)
|
||||||
|
|
@ -148,7 +148,7 @@ class PolymorphicModelBase(ModelBase):
|
||||||
do_app_label_workaround = (meta
|
do_app_label_workaround = (meta
|
||||||
and model_module_name == 'polymorphic'
|
and model_module_name == 'polymorphic'
|
||||||
and model_name == 'PolymorphicModel'
|
and model_name == 'PolymorphicModel'
|
||||||
and getattr(meta, 'app_label', None) is None )
|
and getattr(meta, 'app_label', None) is None)
|
||||||
|
|
||||||
if do_app_label_workaround:
|
if do_app_label_workaround:
|
||||||
meta.app_label = 'poly_dummy_app_label'
|
meta.app_label = 'poly_dummy_app_label'
|
||||||
|
|
@ -162,7 +162,7 @@ class PolymorphicModelBase(ModelBase):
|
||||||
for f in self._meta.fields:
|
for f in self._meta.fields:
|
||||||
if f.name in POLYMORPHIC_SPECIAL_Q_KWORDS:
|
if f.name in POLYMORPHIC_SPECIAL_Q_KWORDS:
|
||||||
e = 'PolymorphicModel: "%s" - field name "%s" is not allowed in polymorphic models'
|
e = 'PolymorphicModel: "%s" - field name "%s" is not allowed in polymorphic models'
|
||||||
raise AssertionError(e % (self.__name__, f.name) )
|
raise AssertionError(e % (self.__name__, f.name))
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def validate_model_manager(self, manager, model_name, manager_name):
|
def validate_model_manager(self, manager, model_name, manager_name):
|
||||||
|
|
@ -192,9 +192,9 @@ class PolymorphicModelBase(ModelBase):
|
||||||
_dumpdata_command_running = (sys.argv[1] == 'dumpdata')
|
_dumpdata_command_running = (sys.argv[1] == 'dumpdata')
|
||||||
|
|
||||||
def __getattribute__(self, name):
|
def __getattribute__(self, name):
|
||||||
if name=='_default_manager':
|
if name == '_default_manager':
|
||||||
if self._dumpdata_command_running:
|
if self._dumpdata_command_running:
|
||||||
frm = inspect.stack()[1] # frm[1] is caller file name, frm[3] is caller function name
|
frm = inspect.stack()[1] # frm[1] is caller file name, frm[3] is caller function name
|
||||||
if 'django/core/management/commands/dumpdata.py' in frm[1]:
|
if 'django/core/management/commands/dumpdata.py' in frm[1]:
|
||||||
return self.base_objects
|
return self.base_objects
|
||||||
#caller_mod_name = inspect.getmodule(frm[0]).__name__ # does not work with python 2.4
|
#caller_mod_name = inspect.getmodule(frm[0]).__name__ # does not work with python 2.4
|
||||||
|
|
|
||||||
|
|
@ -20,36 +20,43 @@ except:
|
||||||
raise TypeError('first argument must be callable')
|
raise TypeError('first argument must be callable')
|
||||||
dict.__init__(self, *a, **kw)
|
dict.__init__(self, *a, **kw)
|
||||||
self.default_factory = default_factory
|
self.default_factory = default_factory
|
||||||
|
|
||||||
def __getitem__(self, key):
|
def __getitem__(self, key):
|
||||||
try:
|
try:
|
||||||
return dict.__getitem__(self, key)
|
return dict.__getitem__(self, key)
|
||||||
except KeyError:
|
except KeyError:
|
||||||
return self.__missing__(key)
|
return self.__missing__(key)
|
||||||
|
|
||||||
def __missing__(self, key):
|
def __missing__(self, key):
|
||||||
if self.default_factory is None:
|
if self.default_factory is None:
|
||||||
raise KeyError(key)
|
raise KeyError(key)
|
||||||
self[key] = value = self.default_factory()
|
self[key] = value = self.default_factory()
|
||||||
return value
|
return value
|
||||||
|
|
||||||
def __reduce__(self):
|
def __reduce__(self):
|
||||||
if self.default_factory is None:
|
if self.default_factory is None:
|
||||||
args = tuple()
|
args = tuple()
|
||||||
else:
|
else:
|
||||||
args = self.default_factory,
|
args = self.default_factory,
|
||||||
return type(self), args, None, None, self.items()
|
return type(self), args, None, None, self.items()
|
||||||
|
|
||||||
def copy(self):
|
def copy(self):
|
||||||
return self.__copy__()
|
return self.__copy__()
|
||||||
|
|
||||||
def __copy__(self):
|
def __copy__(self):
|
||||||
return type(self)(self.default_factory, self)
|
return type(self)(self.default_factory, self)
|
||||||
|
|
||||||
def __deepcopy__(self, memo):
|
def __deepcopy__(self, memo):
|
||||||
import copy
|
import copy
|
||||||
return type(self)(self.default_factory,
|
return type(self)(self.default_factory, copy.deepcopy(self.items()))
|
||||||
copy.deepcopy(self.items()))
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return 'defaultdict(%s, %s)' % (self.default_factory, dict.__repr__(self))
|
return 'defaultdict(%s, %s)' % (self.default_factory, dict.__repr__(self))
|
||||||
|
|
||||||
|
|
||||||
if getattr(str,'partition',None):
|
if getattr(str, 'partition', None):
|
||||||
def compat_partition(s,sep): return s.partition(sep)
|
def compat_partition(s, sep):
|
||||||
|
return s.partition(sep)
|
||||||
else:
|
else:
|
||||||
""" from:
|
""" from:
|
||||||
http://mail.python.org/pipermail/python-dev/2005-September/055962.html
|
http://mail.python.org/pipermail/python-dev/2005-September/055962.html
|
||||||
|
|
@ -82,4 +89,3 @@ else:
|
||||||
assert ''.join(result) == s
|
assert ''.join(result) == s
|
||||||
assert result[1] == '' or result[1] is sep
|
assert result[1] == '' or result[1] is sep
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -37,4 +37,3 @@ class PolymorphicManager(models.Manager):
|
||||||
|
|
||||||
def __unicode__(self):
|
def __unicode__(self):
|
||||||
return u'%s (PolymorphicManager) using %s' % (self.__class__.__name__, self.queryset_class.__name__)
|
return u'%s (PolymorphicManager) using %s' % (self.__class__.__name__, self.queryset_class.__name__)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ http://bitbucket.org/bconstantin/django_polymorphic
|
||||||
|
|
||||||
Copyright:
|
Copyright:
|
||||||
This code and affiliated files are (C) by Bert Constantin and individual contributors.
|
This code and affiliated files are (C) by Bert Constantin and individual contributors.
|
||||||
Please see LICENSE and AUTHORS for more information.
|
Please see LICENSE and AUTHORS for more information.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from django.db import models
|
from django.db import models
|
||||||
|
|
@ -23,7 +23,7 @@ from base import PolymorphicModelBase
|
||||||
from manager import PolymorphicManager
|
from manager import PolymorphicManager
|
||||||
from query_translate import translate_polymorphic_Q_object
|
from query_translate import translate_polymorphic_Q_object
|
||||||
|
|
||||||
|
|
||||||
###################################################################################
|
###################################################################################
|
||||||
### PolymorphicModel
|
### PolymorphicModel
|
||||||
|
|
||||||
|
|
@ -31,18 +31,18 @@ class PolymorphicModel(models.Model):
|
||||||
"""
|
"""
|
||||||
Abstract base class that provides polymorphic behaviour
|
Abstract base class that provides polymorphic behaviour
|
||||||
for any model directly or indirectly derived from it.
|
for any model directly or indirectly derived from it.
|
||||||
|
|
||||||
For usage instructions & examples please see documentation.
|
For usage instructions & examples please see documentation.
|
||||||
|
|
||||||
PolymorphicModel declares one field for internal use (polymorphic_ctype)
|
PolymorphicModel declares one field for internal use (polymorphic_ctype)
|
||||||
and provides a polymorphic manager as the default manager
|
and provides a polymorphic manager as the default manager
|
||||||
(and as 'objects').
|
(and as 'objects').
|
||||||
|
|
||||||
PolymorphicModel overrides the save() and __init__ methods.
|
PolymorphicModel overrides the save() and __init__ methods.
|
||||||
|
|
||||||
If your derived class overrides any of these methods as well, then you need
|
If your derived class overrides any of these methods as well, then you need
|
||||||
to take care that you correctly call the method of the superclass, like:
|
to take care that you correctly call the method of the superclass, like:
|
||||||
|
|
||||||
super(YourClass,self).save(*args,**kwargs)
|
super(YourClass,self).save(*args,**kwargs)
|
||||||
"""
|
"""
|
||||||
__metaclass__ = PolymorphicModelBase
|
__metaclass__ = PolymorphicModelBase
|
||||||
|
|
@ -57,23 +57,23 @@ class PolymorphicModel(models.Model):
|
||||||
abstract = True
|
abstract = True
|
||||||
|
|
||||||
# avoid ContentType related field accessor clash (an error emitted by model validation)
|
# avoid ContentType related field accessor clash (an error emitted by model validation)
|
||||||
# we really should use both app_label and model name, but this is only possible since Django 1.2
|
# we really should use both app_label and model name, but this is only possible since Django 1.2
|
||||||
if django_VERSION[0] <= 1 and django_VERSION[1] <= 1:
|
if django_VERSION[0] <= 1 and django_VERSION[1] <= 1:
|
||||||
p_related_name_template = 'polymorphic_%(class)s_set'
|
p_related_name_template = 'polymorphic_%(class)s_set'
|
||||||
else:
|
else:
|
||||||
p_related_name_template = 'polymorphic_%(app_label)s.%(class)s_set'
|
p_related_name_template = 'polymorphic_%(app_label)s.%(class)s_set'
|
||||||
polymorphic_ctype = models.ForeignKey(ContentType, null=True, editable=False,
|
polymorphic_ctype = models.ForeignKey(ContentType, null=True, editable=False,
|
||||||
related_name=p_related_name_template)
|
related_name=p_related_name_template)
|
||||||
|
|
||||||
# some applications want to know the name of the fields that are added to its models
|
# some applications want to know the name of the fields that are added to its models
|
||||||
polymorphic_internal_model_fields = [ 'polymorphic_ctype' ]
|
polymorphic_internal_model_fields = ['polymorphic_ctype']
|
||||||
|
|
||||||
objects = PolymorphicManager()
|
objects = PolymorphicManager()
|
||||||
base_objects = models.Manager()
|
base_objects = models.Manager()
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def translate_polymorphic_Q_object(self_class,q):
|
def translate_polymorphic_Q_object(self_class, q):
|
||||||
return translate_polymorphic_Q_object(self_class,q)
|
return translate_polymorphic_Q_object(self_class, q)
|
||||||
|
|
||||||
def pre_save_polymorphic(self):
|
def pre_save_polymorphic(self):
|
||||||
"""Normally not needed.
|
"""Normally not needed.
|
||||||
|
|
@ -96,18 +96,18 @@ class PolymorphicModel(models.Model):
|
||||||
"""Normally not needed.
|
"""Normally not needed.
|
||||||
If a non-polymorphic manager (like base_objects) has been used to
|
If a non-polymorphic manager (like base_objects) has been used to
|
||||||
retrieve objects, then the real class/type of these objects may be
|
retrieve objects, then the real class/type of these objects may be
|
||||||
determined using this method."""
|
determined using this method."""
|
||||||
# the following line would be the easiest way to do this, but it produces sql queries
|
# the following line would be the easiest way to do this, but it produces sql queries
|
||||||
#return self.polymorphic_ctype.model_class()
|
#return self.polymorphic_ctype.model_class()
|
||||||
# so we use the following version, which uses the CopntentType manager cache
|
# so we use the following version, which uses the CopntentType manager cache
|
||||||
return ContentType.objects.get_for_id(self.polymorphic_ctype_id).model_class()
|
return ContentType.objects.get_for_id(self.polymorphic_ctype_id).model_class()
|
||||||
|
|
||||||
def get_real_instance(self):
|
def get_real_instance(self):
|
||||||
"""Normally not needed.
|
"""Normally not needed.
|
||||||
If a non-polymorphic manager (like base_objects) has been used to
|
If a non-polymorphic manager (like base_objects) has been used to
|
||||||
retrieve objects, then the complete object with it's real class/type
|
retrieve objects, then the complete object with it's real class/type
|
||||||
and all fields may be retrieved with this method.
|
and all fields may be retrieved with this method.
|
||||||
Each method call executes one db query (if necessary)."""
|
Each method call executes one db query (if necessary)."""
|
||||||
real_model = self.get_real_instance_class()
|
real_model = self.get_real_instance_class()
|
||||||
if real_model == self.__class__:
|
if real_model == self.__class__:
|
||||||
return self
|
return self
|
||||||
|
|
@ -147,11 +147,11 @@ class PolymorphicModel(models.Model):
|
||||||
subclasses_and_superclasses_accessors = self._get_inheritance_relation_fields_and_models()
|
subclasses_and_superclasses_accessors = self._get_inheritance_relation_fields_and_models()
|
||||||
|
|
||||||
from django.db.models.fields.related import SingleRelatedObjectDescriptor, ReverseSingleRelatedObjectDescriptor
|
from django.db.models.fields.related import SingleRelatedObjectDescriptor, ReverseSingleRelatedObjectDescriptor
|
||||||
for name,model in subclasses_and_superclasses_accessors.iteritems():
|
for name, model in subclasses_and_superclasses_accessors.iteritems():
|
||||||
orig_accessor = getattr(self.__class__, name, None)
|
orig_accessor = getattr(self.__class__, name, None)
|
||||||
if type(orig_accessor) in [SingleRelatedObjectDescriptor,ReverseSingleRelatedObjectDescriptor]:
|
if type(orig_accessor) in [SingleRelatedObjectDescriptor, ReverseSingleRelatedObjectDescriptor]:
|
||||||
#print >>sys.stderr, '---------- replacing',name, orig_accessor
|
#print >>sys.stderr, '---------- replacing', name, orig_accessor, '->', model
|
||||||
setattr(self.__class__, name, property(create_accessor_function_for_model(model, name)) )
|
setattr(self.__class__, name, property(create_accessor_function_for_model(model, name)))
|
||||||
|
|
||||||
def _get_inheritance_relation_fields_and_models(self):
|
def _get_inheritance_relation_fields_and_models(self):
|
||||||
"""helper function for __init__:
|
"""helper function for __init__:
|
||||||
|
|
@ -167,8 +167,8 @@ class PolymorphicModel(models.Model):
|
||||||
if (issubclass(model, models.Model)
|
if (issubclass(model, models.Model)
|
||||||
and model != models.Model
|
and model != models.Model
|
||||||
and model != self.__class__
|
and model != self.__class__
|
||||||
and model != PolymorphicModel ):
|
and model != PolymorphicModel):
|
||||||
add_model(model,as_ptr,result)
|
add_model(model, as_ptr, result)
|
||||||
|
|
||||||
def add_all_super_models(model, result):
|
def add_all_super_models(model, result):
|
||||||
add_model_if_regular(model, True, result)
|
add_model_if_regular(model, True, result)
|
||||||
|
|
@ -180,6 +180,6 @@ class PolymorphicModel(models.Model):
|
||||||
add_model_if_regular(b, False, result)
|
add_model_if_regular(b, False, result)
|
||||||
|
|
||||||
result = {}
|
result = {}
|
||||||
add_all_super_models(self.__class__,result)
|
add_all_super_models(self.__class__, result)
|
||||||
add_all_sub_models(self.__class__,result)
|
add_all_sub_models(self.__class__, result)
|
||||||
return result
|
return result
|
||||||
|
|
|
||||||
|
|
@ -60,13 +60,13 @@ class PolymorphicQuerySet(QuerySet):
|
||||||
|
|
||||||
def _filter_or_exclude(self, negate, *args, **kwargs):
|
def _filter_or_exclude(self, negate, *args, **kwargs):
|
||||||
"We override this internal Django functon as it is used for all filter member functions."
|
"We override this internal Django functon as it is used for all filter member functions."
|
||||||
translate_polymorphic_filter_definitions_in_args(self.model, args) # the Q objects
|
translate_polymorphic_filter_definitions_in_args(self.model, args) # the Q objects
|
||||||
additional_args = translate_polymorphic_filter_definitions_in_kwargs(self.model, kwargs) # filter_field='data'
|
additional_args = translate_polymorphic_filter_definitions_in_kwargs(self.model, kwargs) # filter_field='data'
|
||||||
return super(PolymorphicQuerySet, self)._filter_or_exclude(negate, *(list(args) + additional_args), **kwargs)
|
return super(PolymorphicQuerySet, self)._filter_or_exclude(negate, *(list(args) + additional_args), **kwargs)
|
||||||
|
|
||||||
def order_by(self, *args, **kwargs):
|
def order_by(self, *args, **kwargs):
|
||||||
"""translate the field paths in the args, then call vanilla order_by."""
|
"""translate the field paths in the args, then call vanilla order_by."""
|
||||||
new_args = [ translate_polymorphic_field_path(self.model, a) for a in args ]
|
new_args = [translate_polymorphic_field_path(self.model, a) for a in args]
|
||||||
return super(PolymorphicQuerySet, self).order_by(*new_args, **kwargs)
|
return super(PolymorphicQuerySet, self).order_by(*new_args, **kwargs)
|
||||||
|
|
||||||
def _process_aggregate_args(self, args, kwargs):
|
def _process_aggregate_args(self, args, kwargs):
|
||||||
|
|
@ -170,12 +170,12 @@ class PolymorphicQuerySet(QuerySet):
|
||||||
# Then we copy the extra() select fields from the base objects to the real objects.
|
# Then we copy the extra() select fields from the base objects to the real objects.
|
||||||
# TODO: defer(), only(): support for these would be around here
|
# TODO: defer(), only(): support for these would be around here
|
||||||
for modelclass, idlist in idlist_per_model.items():
|
for modelclass, idlist in idlist_per_model.items():
|
||||||
qs = modelclass.base_objects.filter(pk__in=idlist) # use pk__in instead ####
|
qs = modelclass.base_objects.filter(pk__in=idlist) # use pk__in instead ####
|
||||||
qs.dup_select_related(self) # copy select related configuration to new qs
|
qs.dup_select_related(self) # copy select related configuration to new qs
|
||||||
|
|
||||||
for o in qs:
|
for o in qs:
|
||||||
o_pk=getattr(o,pk_name)
|
o_pk = getattr(o, pk_name)
|
||||||
|
|
||||||
if self.query.aggregates:
|
if self.query.aggregates:
|
||||||
for anno_field_name in self.query.aggregates.keys():
|
for anno_field_name in self.query.aggregates.keys():
|
||||||
attr = getattr(base_result_objects_by_id[o_pk], anno_field_name)
|
attr = getattr(base_result_objects_by_id[o_pk], anno_field_name)
|
||||||
|
|
@ -189,20 +189,20 @@ class PolymorphicQuerySet(QuerySet):
|
||||||
results[o_pk] = o
|
results[o_pk] = o
|
||||||
|
|
||||||
# re-create correct order and return result list
|
# re-create correct order and return result list
|
||||||
resultlist = [ results[ordered_id] for ordered_id in ordered_id_list if ordered_id in results ]
|
resultlist = [results[ordered_id] for ordered_id in ordered_id_list if ordered_id in results]
|
||||||
|
|
||||||
# set polymorphic_annotate_names in all objects (currently just used for debugging/printing)
|
# set polymorphic_annotate_names in all objects (currently just used for debugging/printing)
|
||||||
if self.query.aggregates:
|
if self.query.aggregates:
|
||||||
annotate_names=self.query.aggregates.keys() # get annotate field list
|
annotate_names = self.query.aggregates.keys() # get annotate field list
|
||||||
for o in resultlist:
|
for o in resultlist:
|
||||||
o.polymorphic_annotate_names=annotate_names
|
o.polymorphic_annotate_names = annotate_names
|
||||||
|
|
||||||
# set polymorphic_extra_select_names in all objects (currently just used for debugging/printing)
|
# set polymorphic_extra_select_names in all objects (currently just used for debugging/printing)
|
||||||
if self.query.extra_select:
|
if self.query.extra_select:
|
||||||
extra_select_names=self.query.extra_select.keys() # get extra select field list
|
extra_select_names = self.query.extra_select.keys() # get extra select field list
|
||||||
for o in resultlist:
|
for o in resultlist:
|
||||||
o.polymorphic_extra_select_names=extra_select_names
|
o.polymorphic_extra_select_names = extra_select_names
|
||||||
|
|
||||||
return resultlist
|
return resultlist
|
||||||
|
|
||||||
def iterator(self):
|
def iterator(self):
|
||||||
|
|
@ -250,14 +250,14 @@ class PolymorphicQuerySet(QuerySet):
|
||||||
|
|
||||||
def __repr__(self, *args, **kwargs):
|
def __repr__(self, *args, **kwargs):
|
||||||
if self.model.polymorphic_query_multiline_output:
|
if self.model.polymorphic_query_multiline_output:
|
||||||
result = [ repr(o) for o in self.all() ]
|
result = [repr(o) for o in self.all()]
|
||||||
return '[ ' + ',\n '.join(result) + ' ]'
|
return '[ ' + ',\n '.join(result) + ' ]'
|
||||||
else:
|
else:
|
||||||
return super(PolymorphicQuerySet,self).__repr__(*args, **kwargs)
|
return super(PolymorphicQuerySet, self).__repr__(*args, **kwargs)
|
||||||
|
|
||||||
class _p_list_class(list):
|
class _p_list_class(list):
|
||||||
def __repr__(self, *args, **kwargs):
|
def __repr__(self, *args, **kwargs):
|
||||||
result = [ repr(o) for o in self ]
|
result = [repr(o) for o in self]
|
||||||
return '[ ' + ',\n '.join(result) + ' ]'
|
return '[ ' + ',\n '.join(result) + ' ]'
|
||||||
|
|
||||||
def get_real_instances(self, base_result_objects=None):
|
def get_real_instances(self, base_result_objects=None):
|
||||||
|
|
|
||||||
|
|
@ -47,6 +47,7 @@ def translate_polymorphic_filter_definitions_in_kwargs(queryset_model, kwargs):
|
||||||
|
|
||||||
return additional_args
|
return additional_args
|
||||||
|
|
||||||
|
|
||||||
def translate_polymorphic_Q_object(queryset_model, potential_q_object):
|
def translate_polymorphic_Q_object(queryset_model, potential_q_object):
|
||||||
def tree_node_correct_field_specs(my_model, node):
|
def tree_node_correct_field_specs(my_model, node):
|
||||||
" process all children of this Q node "
|
" process all children of this Q node "
|
||||||
|
|
@ -68,6 +69,7 @@ def translate_polymorphic_Q_object(queryset_model, potential_q_object):
|
||||||
|
|
||||||
return potential_q_object
|
return potential_q_object
|
||||||
|
|
||||||
|
|
||||||
def translate_polymorphic_filter_definitions_in_args(queryset_model, args):
|
def translate_polymorphic_filter_definitions_in_args(queryset_model, args):
|
||||||
"""
|
"""
|
||||||
Translate the non-keyword argument list for PolymorphicQuerySet.filter()
|
Translate the non-keyword argument list for PolymorphicQuerySet.filter()
|
||||||
|
|
@ -104,7 +106,7 @@ def _translate_polymorphic_filter_definition(queryset_model, field_path, field_v
|
||||||
elif field_path == 'not_instance_of':
|
elif field_path == 'not_instance_of':
|
||||||
return _create_model_filter_Q(field_val, not_instance_of=True)
|
return _create_model_filter_Q(field_val, not_instance_of=True)
|
||||||
elif not '___' in field_path:
|
elif not '___' in field_path:
|
||||||
return None #no change
|
return None # no change
|
||||||
|
|
||||||
# filter expression contains '___' (i.e. filter for polymorphic field)
|
# filter expression contains '___' (i.e. filter for polymorphic field)
|
||||||
# => get the model class specified in the filter expression
|
# => get the model class specified in the filter expression
|
||||||
|
|
@ -184,7 +186,7 @@ def translate_polymorphic_field_path(queryset_model, field_path):
|
||||||
newpath = '-'
|
newpath = '-'
|
||||||
else:
|
else:
|
||||||
newpath = ''
|
newpath = ''
|
||||||
|
|
||||||
newpath += basepath
|
newpath += basepath
|
||||||
if basepath:
|
if basepath:
|
||||||
newpath += '__'
|
newpath += '__'
|
||||||
|
|
@ -223,10 +225,9 @@ def _create_model_filter_Q(modellist, not_instance_of=False):
|
||||||
q = q | q_class_with_subclasses(subclass)
|
q = q | q_class_with_subclasses(subclass)
|
||||||
return q
|
return q
|
||||||
|
|
||||||
qlist = [ q_class_with_subclasses(m) for m in modellist ]
|
qlist = [q_class_with_subclasses(m) for m in modellist]
|
||||||
|
|
||||||
q_ored = reduce(lambda a, b: a | b, qlist)
|
q_ored = reduce(lambda a, b: a | b, qlist)
|
||||||
if not_instance_of:
|
if not_instance_of:
|
||||||
q_ored = ~q_ored
|
q_ored = ~q_ored
|
||||||
return q_ored
|
return q_ored
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,10 +2,11 @@
|
||||||
|
|
||||||
from django.db import models
|
from django.db import models
|
||||||
|
|
||||||
|
|
||||||
class ShowFieldBase(object):
|
class ShowFieldBase(object):
|
||||||
""" base class for the ShowField... model mixins, does the work """
|
""" base class for the ShowField... model mixins, does the work """
|
||||||
|
|
||||||
polymorphic_query_multiline_output = True # cause nicer multiline PolymorphicQuery output
|
polymorphic_query_multiline_output = True # cause nicer multiline PolymorphicQuery output
|
||||||
|
|
||||||
polymorphic_showfield_type = False
|
polymorphic_showfield_type = False
|
||||||
polymorphic_showfield_content = False
|
polymorphic_showfield_content = False
|
||||||
|
|
@ -32,14 +33,14 @@ class ShowFieldBase(object):
|
||||||
out += content.__class__.__name__
|
out += content.__class__.__name__
|
||||||
elif issubclass(field_type, models.ManyToManyField):
|
elif issubclass(field_type, models.ManyToManyField):
|
||||||
out += '%d' % content.count()
|
out += '%d' % content.count()
|
||||||
elif type(content) in (int,long):
|
elif type(content) in (int, long):
|
||||||
out += unicode(content)
|
out += unicode(content)
|
||||||
elif content is None:
|
elif content is None:
|
||||||
out += 'None'
|
out += 'None'
|
||||||
else:
|
else:
|
||||||
txt=unicode(content)
|
txt = unicode(content)
|
||||||
if len(txt)>self.polymorphic_showfield_max_field_width:
|
if len(txt) > self.polymorphic_showfield_max_field_width:
|
||||||
txt=txt[:self.polymorphic_showfield_max_field_width-2]+'..'
|
txt = txt[:self.polymorphic_showfield_max_field_width - 2] + '..'
|
||||||
out += '"' + txt + '"'
|
out += '"' + txt + '"'
|
||||||
return out
|
return out
|
||||||
|
|
||||||
|
|
@ -50,14 +51,14 @@ class ShowFieldBase(object):
|
||||||
if field.name in self.polymorphic_internal_model_fields or '_ptr' in field.name:
|
if field.name in self.polymorphic_internal_model_fields or '_ptr' in field.name:
|
||||||
continue
|
continue
|
||||||
if field.name in done_fields:
|
if field.name in done_fields:
|
||||||
continue # work around django diamond inheritance problem
|
continue # work around django diamond inheritance problem
|
||||||
done_fields.add(field.name)
|
done_fields.add(field.name)
|
||||||
|
|
||||||
out = field.name
|
out = field.name
|
||||||
|
|
||||||
# if this is the standard primary key named "id", print it as we did with older versions of django_polymorphic
|
# if this is the standard primary key named "id", print it as we did with older versions of django_polymorphic
|
||||||
if field.primary_key and field.name=='id' and type(field)==models.AutoField:
|
if field.primary_key and field.name == 'id' and type(field) == models.AutoField:
|
||||||
out += ' '+ unicode(getattr(self, field.name))
|
out += ' ' + unicode(getattr(self, field.name))
|
||||||
|
|
||||||
# otherwise, display it just like all other fields (with correct type, shortened content etc.)
|
# otherwise, display it just like all other fields (with correct type, shortened content etc.)
|
||||||
else:
|
else:
|
||||||
|
|
@ -68,13 +69,13 @@ class ShowFieldBase(object):
|
||||||
out += ')'
|
out += ')'
|
||||||
|
|
||||||
if self.polymorphic_showfield_content:
|
if self.polymorphic_showfield_content:
|
||||||
out += self._showfields_get_content(field.name,type(field))
|
out += self._showfields_get_content(field.name, type(field))
|
||||||
|
|
||||||
parts.append((False, out,','))
|
parts.append((False, out, ','))
|
||||||
|
|
||||||
def _showfields_add_dynamic_fields(self, field_list, title, parts):
|
def _showfields_add_dynamic_fields(self, field_list, title, parts):
|
||||||
"helper for __unicode__"
|
"helper for __unicode__"
|
||||||
parts.append( ( True, '- '+title, ':' ) )
|
parts.append((True, '- ' + title, ':'))
|
||||||
for field_name in field_list:
|
for field_name in field_list:
|
||||||
out = field_name
|
out = field_name
|
||||||
content = getattr(self, field_name)
|
content = getattr(self, field_name)
|
||||||
|
|
@ -83,67 +84,74 @@ class ShowFieldBase(object):
|
||||||
if self.polymorphic_showfield_content:
|
if self.polymorphic_showfield_content:
|
||||||
out += self._showfields_get_content(field_name)
|
out += self._showfields_get_content(field_name)
|
||||||
|
|
||||||
parts.append( ( False, out, ',' ) )
|
parts.append((False, out, ','))
|
||||||
|
|
||||||
def __unicode__(self):
|
def __unicode__(self):
|
||||||
# create list ("parts") containing one tuple for each title/field:
|
# create list ("parts") containing one tuple for each title/field:
|
||||||
# ( bool: new section , item-text , separator to use after item )
|
# ( bool: new section , item-text , separator to use after item )
|
||||||
|
|
||||||
# start with model name
|
# start with model name
|
||||||
parts = [ (True, self.__class__.__name__, ':') ]
|
parts = [(True, self.__class__.__name__, ':')]
|
||||||
|
|
||||||
# add all regular fields
|
# add all regular fields
|
||||||
self._showfields_add_regular_fields(parts)
|
self._showfields_add_regular_fields(parts)
|
||||||
|
|
||||||
# add annotate fields
|
# add annotate fields
|
||||||
if hasattr(self,'polymorphic_annotate_names'):
|
if hasattr(self, 'polymorphic_annotate_names'):
|
||||||
self._showfields_add_dynamic_fields(self.polymorphic_annotate_names, 'Ann', parts)
|
self._showfields_add_dynamic_fields(self.polymorphic_annotate_names, 'Ann', parts)
|
||||||
|
|
||||||
# add extra() select fields
|
# add extra() select fields
|
||||||
if hasattr(self,'polymorphic_extra_select_names'):
|
if hasattr(self, 'polymorphic_extra_select_names'):
|
||||||
self._showfields_add_dynamic_fields(self.polymorphic_extra_select_names, 'Extra', parts)
|
self._showfields_add_dynamic_fields(self.polymorphic_extra_select_names, 'Extra', parts)
|
||||||
|
|
||||||
# format result
|
# format result
|
||||||
|
|
||||||
indent = len(self.__class__.__name__)+5
|
indent = len(self.__class__.__name__) + 5
|
||||||
indentstr = ''.rjust(indent)
|
indentstr = ''.rjust(indent)
|
||||||
out=u''; xpos=0; possible_line_break_pos = None
|
out = u''
|
||||||
|
xpos = 0
|
||||||
|
possible_line_break_pos = None
|
||||||
|
|
||||||
for i in xrange(len(parts)):
|
for i in xrange(len(parts)):
|
||||||
new_section, p, separator = parts[i]
|
new_section, p, separator = parts[i]
|
||||||
final = (i==len(parts)-1)
|
final = (i == len(parts) - 1)
|
||||||
if not final:
|
if not final:
|
||||||
next_new_section, _, _ = parts[i+1]
|
next_new_section, _, _ = parts[i + 1]
|
||||||
|
|
||||||
if ( self.polymorphic_showfield_max_line_width
|
if (self.polymorphic_showfield_max_line_width
|
||||||
and xpos+len(p) > self.polymorphic_showfield_max_line_width
|
and xpos + len(p) > self.polymorphic_showfield_max_line_width
|
||||||
and possible_line_break_pos!=None ):
|
and possible_line_break_pos != None):
|
||||||
rest = out[possible_line_break_pos:]
|
rest = out[possible_line_break_pos:]
|
||||||
out = out[:possible_line_break_pos]
|
out = out[:possible_line_break_pos]
|
||||||
out+= '\n'+indentstr+rest
|
out += '\n' + indentstr + rest
|
||||||
xpos=indent+len(rest)
|
xpos = indent + len(rest)
|
||||||
|
|
||||||
out += p; xpos += len(p)
|
out += p
|
||||||
|
xpos += len(p)
|
||||||
|
|
||||||
if not final:
|
if not final:
|
||||||
if not next_new_section:
|
if not next_new_section:
|
||||||
out += separator; xpos += len(separator)
|
out += separator
|
||||||
out += ' '; xpos += 1
|
xpos += len(separator)
|
||||||
|
out += ' '
|
||||||
|
xpos += 1
|
||||||
|
|
||||||
if not new_section:
|
if not new_section:
|
||||||
possible_line_break_pos=len(out)
|
possible_line_break_pos = len(out)
|
||||||
|
|
||||||
return u'<'+out+'>'
|
return u'<' + out + '>'
|
||||||
|
|
||||||
|
|
||||||
class ShowFieldType(ShowFieldBase):
|
class ShowFieldType(ShowFieldBase):
|
||||||
""" model mixin that shows the object's class and it's field types """
|
""" model mixin that shows the object's class and it's field types """
|
||||||
polymorphic_showfield_type = True
|
polymorphic_showfield_type = True
|
||||||
|
|
||||||
|
|
||||||
class ShowFieldContent(ShowFieldBase):
|
class ShowFieldContent(ShowFieldBase):
|
||||||
""" model mixin that shows the object's class, it's fields and field contents """
|
""" model mixin that shows the object's class, it's fields and field contents """
|
||||||
polymorphic_showfield_content = True
|
polymorphic_showfield_content = True
|
||||||
|
|
||||||
|
|
||||||
class ShowFieldTypeAndContent(ShowFieldBase):
|
class ShowFieldTypeAndContent(ShowFieldBase):
|
||||||
""" model mixin, like ShowFieldContent, but also show field types """
|
""" model mixin, like ShowFieldContent, but also show field types """
|
||||||
polymorphic_showfield_type = True
|
polymorphic_showfield_type = True
|
||||||
|
|
|
||||||
|
|
@ -4,15 +4,15 @@
|
||||||
|
|
||||||
import uuid
|
import uuid
|
||||||
|
|
||||||
from django.forms.util import ValidationError
|
|
||||||
from django import forms
|
from django import forms
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.utils.encoding import smart_unicode
|
from django.utils.encoding import smart_unicode
|
||||||
from django.utils.translation import ugettext_lazy
|
|
||||||
|
|
||||||
class UUIDVersionError(Exception):
|
class UUIDVersionError(Exception):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class UUIDField(models.CharField):
|
class UUIDField(models.CharField):
|
||||||
"""Encode and stores a Python uuid.UUID in a manner that is appropriate
|
"""Encode and stores a Python uuid.UUID in a manner that is appropriate
|
||||||
for the given datatabase that we are using.
|
for the given datatabase that we are using.
|
||||||
|
|
@ -60,24 +60,24 @@ class UUIDField(models.CharField):
|
||||||
|
|
||||||
self.auto = auto
|
self.auto = auto
|
||||||
self.version = version
|
self.version = version
|
||||||
if version==1:
|
if version == 1:
|
||||||
self.node, self.clock_seq = node, clock_seq
|
self.node, self.clock_seq = node, clock_seq
|
||||||
elif version==3 or version==5:
|
elif version == 3 or version == 5:
|
||||||
self.namespace, self.name = namespace, name
|
self.namespace, self.name = namespace, name
|
||||||
|
|
||||||
super(UUIDField, self).__init__(verbose_name=verbose_name,
|
super(UUIDField, self).__init__(verbose_name=verbose_name,
|
||||||
name=name, **kwargs)
|
name=name, **kwargs)
|
||||||
|
|
||||||
def create_uuid(self):
|
def create_uuid(self):
|
||||||
if not self.version or self.version==4:
|
if not self.version or self.version == 4:
|
||||||
return uuid.uuid4()
|
return uuid.uuid4()
|
||||||
elif self.version==1:
|
elif self.version == 1:
|
||||||
return uuid.uuid1(self.node, self.clock_seq)
|
return uuid.uuid1(self.node, self.clock_seq)
|
||||||
elif self.version==2:
|
elif self.version == 2:
|
||||||
raise UUIDVersionError("UUID version 2 is not supported.")
|
raise UUIDVersionError("UUID version 2 is not supported.")
|
||||||
elif self.version==3:
|
elif self.version == 3:
|
||||||
return uuid.uuid3(self.namespace, self.name)
|
return uuid.uuid3(self.namespace, self.name)
|
||||||
elif self.version==5:
|
elif self.version == 5:
|
||||||
return uuid.uuid5(self.namespace, self.name)
|
return uuid.uuid5(self.namespace, self.name)
|
||||||
else:
|
else:
|
||||||
raise UUIDVersionError("UUID version %s is not valid." % self.version)
|
raise UUIDVersionError("UUID version %s is not valid." % self.version)
|
||||||
|
|
@ -116,7 +116,7 @@ class UUIDField(models.CharField):
|
||||||
value = self.create_uuid()
|
value = self.create_uuid()
|
||||||
setattr(model_instance, self.attname, value)
|
setattr(model_instance, self.attname, value)
|
||||||
else:
|
else:
|
||||||
value = super(UUIDField, self).pre_save(model_instance,add)
|
value = super(UUIDField, self).pre_save(model_instance, add)
|
||||||
if self.auto and not value:
|
if self.auto and not value:
|
||||||
value = self.create_uuid()
|
value = self.create_uuid()
|
||||||
setattr(model_instance, self.attname, value)
|
setattr(model_instance, self.attname, value)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue