- renamed ShowField* to ShowFieldType, ShowFieldContent, ShowFieldTypeAndContent, in order to reflect better what they do.
- by default, django_polymorphic's pretty printing of querysets/objects (via ShowField*) is not used anymore - ShowField mixins now also show the annotations (after the regular fields, prepended by "Ann:") - cleaned up implementation.fix_request_path_info
parent
50b54f5aca
commit
01bdb2f9b0
|
|
@ -15,11 +15,14 @@ pushhg
|
|||
pushreg
|
||||
pbackup
|
||||
mcmd.py
|
||||
dbconfig_local.py
|
||||
|
||||
pip-log.txt
|
||||
build
|
||||
ppreadme.py
|
||||
ppdocs.py
|
||||
common.css
|
||||
screen.css
|
||||
README.html
|
||||
DOCS.html
|
||||
|
||||
|
|
|
|||
|
|
@ -22,13 +22,15 @@ class Command(NoArgsCommand):
|
|||
def handle_noargs(self, **options):
|
||||
print 'polycmd - sqlite test db is stored in:',settings.DATABASE_NAME
|
||||
print
|
||||
|
||||
|
||||
"""
|
||||
ModelA.objects.all().delete()
|
||||
o=ModelA.objects.create(field1='A1')
|
||||
o=ModelB.objects.create(field1='B1', field2='B2')
|
||||
o=ModelC.objects.create(field1='C1', field2='C2', field3='C3')
|
||||
print ModelA.objects.all()
|
||||
print
|
||||
"""
|
||||
|
||||
Project.objects.all().delete()
|
||||
o=Project.objects.create(topic="John's gathering")
|
||||
|
|
|
|||
|
|
@ -2,29 +2,24 @@
|
|||
|
||||
from django.db import models
|
||||
|
||||
from polymorphic import PolymorphicModel, PolymorphicManager, PolymorphicQuerySet, ShowFields, ShowFieldsAndTypes
|
||||
from polymorphic import PolymorphicModel, PolymorphicManager, PolymorphicQuerySet
|
||||
from polymorphic.showfields import ShowFieldContent, ShowFieldType, ShowFieldTypeAndContent
|
||||
|
||||
|
||||
class Project(ShowFields, PolymorphicModel):
|
||||
class Project(ShowFieldContent, PolymorphicModel):
|
||||
topic = models.CharField(max_length=30)
|
||||
class ArtProject(Project):
|
||||
artist = models.CharField(max_length=30)
|
||||
class ResearchProject(Project):
|
||||
supervisor = models.CharField(max_length=30)
|
||||
|
||||
class ModelA(PolymorphicModel):
|
||||
class ModelA(ShowFieldType, PolymorphicModel):
|
||||
field1 = models.CharField(max_length=10)
|
||||
class ModelB(ModelA):
|
||||
field2 = models.CharField(max_length=10)
|
||||
class ModelC(ModelB):
|
||||
field3 = models.CharField(max_length=10)
|
||||
|
||||
class SModelA(ShowFieldsAndTypes, PolymorphicModel):
|
||||
field1 = models.CharField(max_length=10)
|
||||
class SModelB(SModelA):
|
||||
field2 = models.CharField(max_length=10)
|
||||
class SModelC(SModelB):
|
||||
field3 = models.CharField(max_length=10)
|
||||
|
||||
# for Django 1.2+, test models with same names in different apps
|
||||
# (the other models with identical names are in polymorphic/tests.py)
|
||||
|
|
|
|||
|
|
@ -10,7 +10,8 @@ Please see LICENSE and AUTHORS for more information.
|
|||
from polymorphic_model import PolymorphicModel
|
||||
from manager import PolymorphicManager
|
||||
from query import PolymorphicQuerySet
|
||||
from showfields import ShowFields, ShowFieldsAndTypes
|
||||
from showfields import ShowFieldContent, ShowFieldType, ShowFieldTypeAndContent
|
||||
#from showfields import ShowFieldTypes, ShowFields, ShowFieldsAndTypes # import old names for compatibility
|
||||
|
||||
|
||||
VERSION = (0, 5, 0, 'beta')
|
||||
|
|
|
|||
|
|
@ -26,13 +26,13 @@ from django import VERSION as django_VERSION
|
|||
from base import PolymorphicModelBase
|
||||
from manager import PolymorphicManager
|
||||
from query import PolymorphicQuerySet
|
||||
from showfields import ShowFieldTypes
|
||||
from showfields import ShowFieldType
|
||||
|
||||
|
||||
###################################################################################
|
||||
### PolymorphicModel
|
||||
|
||||
class PolymorphicModel(ShowFieldTypes, models.Model):
|
||||
class PolymorphicModel(models.Model):
|
||||
"""
|
||||
Abstract base class that provides polymorphic behaviour
|
||||
for any model directly or indirectly derived from it.
|
||||
|
|
@ -53,7 +53,11 @@ class PolymorphicModel(ShowFieldTypes, models.Model):
|
|||
"""
|
||||
__metaclass__ = PolymorphicModelBase
|
||||
|
||||
polymorphic_model_marker = True # for PolymorphicModelBase
|
||||
# for PolymorphicModelBase, so it can tell which models are polymorphic and which are not (duck typing)
|
||||
polymorphic_model_marker = True
|
||||
|
||||
# for PolymorphicQuery, True => an overloaded __repr__ with nicer multi-line output is used by PolymorphicQuery
|
||||
polymorphic_query_multiline_output = False
|
||||
|
||||
class Meta:
|
||||
abstract = True
|
||||
|
|
@ -66,7 +70,7 @@ class PolymorphicModel(ShowFieldTypes, models.Model):
|
|||
p_related_name_template = 'polymorphic_%(app_label)s.%(class)s_set'
|
||||
polymorphic_ctype = models.ForeignKey(ContentType, null=True, editable=False,
|
||||
related_name=p_related_name_template)
|
||||
|
||||
|
||||
# some applications want to know the name of the fields that are added to its models
|
||||
polymorphic_internal_model_fields = [ 'polymorphic_ctype' ]
|
||||
|
||||
|
|
@ -130,10 +134,12 @@ class PolymorphicModel(ShowFieldTypes, models.Model):
|
|||
name = model.__name__.lower()
|
||||
if as_ptr: name+='_ptr'
|
||||
result[name] = model
|
||||
|
||||
def add_all_base_models(model, result):
|
||||
add_if_regular_sub_or_super_class(model, True, result)
|
||||
for b in model.__bases__:
|
||||
add_all_base_models(b, result)
|
||||
|
||||
def add_sub_models(model, result):
|
||||
for b in model.__subclasses__():
|
||||
add_if_regular_sub_or_super_class(b, False, result)
|
||||
|
|
@ -150,6 +156,6 @@ class PolymorphicModel(ShowFieldTypes, models.Model):
|
|||
attr = model.base_objects.get(id=id)
|
||||
#print '---',self.__class__.__name__,name
|
||||
return attr
|
||||
|
||||
return super(PolymorphicModel, self).__getattribute__(name)
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -144,6 +144,7 @@ class PolymorphicQuerySet(QuerySet):
|
|||
for modelclass, idlist in idlist_per_model.items():
|
||||
qs = modelclass.base_objects.filter(id__in=idlist)
|
||||
qs.dup_select_related(self) # copy select related configuration to new qs
|
||||
|
||||
for o in qs:
|
||||
if self.query.aggregates:
|
||||
for anno in self.query.aggregates.keys():
|
||||
|
|
@ -153,6 +154,13 @@ class PolymorphicQuerySet(QuerySet):
|
|||
|
||||
# re-create correct order and return result list
|
||||
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)
|
||||
if self.query.aggregates:
|
||||
annotate_names=self.query.aggregates.keys() # get annotate fields list
|
||||
for o in resultlist:
|
||||
o.polymorphic_annotate_names=annotate_names
|
||||
|
||||
return resultlist
|
||||
|
||||
def iterator(self):
|
||||
|
|
@ -182,7 +190,9 @@ class PolymorphicQuerySet(QuerySet):
|
|||
reached_end = False
|
||||
|
||||
for i in range(Polymorphic_QuerySet_objects_per_request):
|
||||
try: base_result_objects.append(base_iter.next())
|
||||
try:
|
||||
o=base_iter.next()
|
||||
base_result_objects.append(o)
|
||||
except StopIteration:
|
||||
reached_end = True
|
||||
break
|
||||
|
|
@ -194,8 +204,10 @@ class PolymorphicQuerySet(QuerySet):
|
|||
|
||||
if reached_end: raise StopIteration
|
||||
|
||||
def __repr__(self):
|
||||
result = [ repr(o) for o in self.all() ]
|
||||
return '[ ' + ',\n '.join(result) + ' ]'
|
||||
|
||||
def __repr__(self, *args, **kwargs):
|
||||
if self.model.polymorphic_query_multiline_output:
|
||||
result = [ repr(o) for o in self.all() ]
|
||||
return '[ ' + ',\n '.join(result) + ' ]'
|
||||
else:
|
||||
return super(PolymorphicQuerySet,self).__repr__(*args, **kwargs)
|
||||
|
||||
|
|
|
|||
|
|
@ -2,49 +2,67 @@
|
|||
|
||||
from django.db import models
|
||||
|
||||
def _represent_foreign_key(o):
|
||||
if o is None:
|
||||
out = '"None"'
|
||||
else:
|
||||
out = '"' + o.__class__.__name__ + '"'
|
||||
return out
|
||||
|
||||
class ShowFieldsAndTypes(object):
|
||||
""" model mixin, like ShowFields, but also show field types """
|
||||
def __repr__(self):
|
||||
out = 'id ' + str(self.pk)
|
||||
for f in self._meta.fields:
|
||||
if f.name in [ 'id' ] + self.polymorphic_internal_model_fields or 'ptr' in f.name: continue
|
||||
out += ', ' + f.name + ' (' + type(f).__name__ + ')'
|
||||
if isinstance(f, (models.ForeignKey)):
|
||||
o = getattr(self, f.name)
|
||||
out += ': ' + _represent_foreign_key(o)
|
||||
else:
|
||||
out += ': "' + getattr(self, f.name) + '"'
|
||||
return '<' + self.__class__.__name__ + ': ' + out + '>'
|
||||
class ShowFieldBase(object):
|
||||
""" base class for the ShowField... model mixins, does the work """
|
||||
polymorphic_query_multiline_output = True # cause nicer multiline PolymorphicQuery output
|
||||
|
||||
polymorphic_showfield_type = False
|
||||
polymorphic_showfield_content = False
|
||||
|
||||
class ShowFields(object):
|
||||
""" model mixin that shows the object's class, it's fields and field contents """
|
||||
def __repr__(self):
|
||||
out = 'id ' + str(self.pk) + ', '
|
||||
for f in self._meta.fields:
|
||||
return self.__unicode__()
|
||||
|
||||
def __unicode__(self):
|
||||
out = u'<'+self.__class__.__name__+': id %s' % unicode(self.pk)
|
||||
for f in self._meta.fields + self._meta.many_to_many:
|
||||
|
||||
if f.name in [ 'id' ] + self.polymorphic_internal_model_fields or 'ptr' in f.name: continue
|
||||
out += ', ' + f.name
|
||||
if isinstance(f, (models.ForeignKey)):
|
||||
|
||||
if self.polymorphic_showfield_type:
|
||||
out += ' (' + type(f).__name__ + ')'
|
||||
|
||||
if self.polymorphic_showfield_content:
|
||||
o = getattr(self, f.name)
|
||||
out += ': ' + _represent_foreign_key(o)
|
||||
else:
|
||||
out += ': "' + getattr(self, f.name) + '"'
|
||||
return '<' + (self.__class__.__name__ + ': ') + out + '>'
|
||||
|
||||
class ShowFieldTypes(object):
|
||||
""" INTERNAL; don't use this!
|
||||
This mixin is already used by default by PolymorphicModel.
|
||||
(model mixin that shows the object's class and it's field types) """
|
||||
def __repr__(self):
|
||||
out = self.__class__.__name__ + ': id ' + str(self.pk)
|
||||
for f in self._meta.fields:
|
||||
if f.name in [ 'id' ] + self.polymorphic_internal_model_fields or 'ptr' in f.name: continue
|
||||
out += ', ' + f.name + ' (' + type(f).__name__ + ')'
|
||||
return '<' + out + '>'
|
||||
if isinstance(f, (models.ForeignKey)):
|
||||
out += ': ' + ( '"None"' if o is None else '"' + o.__class__.__name__ + '"' )
|
||||
|
||||
elif isinstance(f, (models.ManyToManyField)):
|
||||
out += ': %d' % o.count()
|
||||
|
||||
else:
|
||||
out += ': "' + unicode(o) + '"'
|
||||
|
||||
if hasattr(self,'polymorphic_annotate_names'):
|
||||
out += ' - Ann: '
|
||||
for an in self.polymorphic_annotate_names:
|
||||
if an != self.polymorphic_annotate_names[0]:
|
||||
out += ', '
|
||||
out += an
|
||||
if self.polymorphic_showfield_type:
|
||||
out += ' (' + type(getattr(self, an)).__name__ + ')'
|
||||
if self.polymorphic_showfield_content:
|
||||
out += ': "' + unicode(getattr(self, an)) + '"'
|
||||
|
||||
return out+'>'
|
||||
|
||||
class ShowFieldType(ShowFieldBase):
|
||||
""" model mixin that shows the object's class and it's field types """
|
||||
polymorphic_showfield_type = True
|
||||
|
||||
class ShowFieldContent(ShowFieldBase):
|
||||
""" model mixin that shows the object's class, it's fields and field contents """
|
||||
polymorphic_showfield_content = True
|
||||
|
||||
class ShowFieldTypeAndContent(ShowFieldBase):
|
||||
""" model mixin, like ShowFieldContent, but also show field types """
|
||||
polymorphic_showfield_type = True
|
||||
polymorphic_showfield_content = True
|
||||
|
||||
|
||||
# compatibility with old class names
|
||||
ShowFieldTypes = ShowFieldType
|
||||
ShowFields = ShowFieldContent
|
||||
ShowFieldsAndTypes = ShowFieldTypeAndContent
|
||||
|
|
|
|||
|
|
@ -7,11 +7,12 @@ import settings
|
|||
|
||||
from django.test import TestCase
|
||||
from django.db.models.query import QuerySet
|
||||
from django.db.models import Q
|
||||
from django.db.models import Q,Count
|
||||
from django.db import models
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from pprint import pprint
|
||||
|
||||
from polymorphic import PolymorphicModel, PolymorphicManager, PolymorphicQuerySet, ShowFields, ShowFieldsAndTypes, get_version
|
||||
from polymorphic import PolymorphicModel, PolymorphicManager, PolymorphicQuerySet, ShowFieldContent, ShowFieldType, ShowFieldTypeAndContent, get_version
|
||||
|
||||
class PlainA(models.Model):
|
||||
field1 = models.CharField(max_length=10)
|
||||
|
|
@ -20,14 +21,24 @@ class PlainB(PlainA):
|
|||
class PlainC(PlainB):
|
||||
field3 = models.CharField(max_length=10)
|
||||
|
||||
class Model2A(PolymorphicModel):
|
||||
class Model2A(ShowFieldType, PolymorphicModel):
|
||||
field1 = models.CharField(max_length=10)
|
||||
class Model2B(Model2A):
|
||||
field2 = models.CharField(max_length=10)
|
||||
class Model2C(Model2B):
|
||||
field3 = models.CharField(max_length=10)
|
||||
|
||||
class Base(PolymorphicModel):
|
||||
class ModelShow1(ShowFieldType,PolymorphicModel):
|
||||
field1 = models.CharField(max_length=10)
|
||||
m2m = models.ManyToManyField('self')
|
||||
class ModelShow2(ShowFieldContent, PolymorphicModel):
|
||||
field1 = models.CharField(max_length=10)
|
||||
m2m = models.ManyToManyField('self')
|
||||
class ModelShow3(ShowFieldTypeAndContent, PolymorphicModel):
|
||||
field1 = models.CharField(max_length=10)
|
||||
m2m = models.ManyToManyField('self')
|
||||
|
||||
class Base(ShowFieldType, PolymorphicModel):
|
||||
field_b = models.CharField(max_length=10)
|
||||
class ModelX(Base):
|
||||
field_x = models.CharField(max_length=10)
|
||||
|
|
@ -36,7 +47,7 @@ class ModelY(Base):
|
|||
|
||||
class Enhance_Plain(models.Model):
|
||||
field_p = models.CharField(max_length=10)
|
||||
class Enhance_Base(ShowFieldsAndTypes, PolymorphicModel):
|
||||
class Enhance_Base(ShowFieldTypeAndContent, PolymorphicModel):
|
||||
field_b = models.CharField(max_length=10)
|
||||
class Enhance_Inherit(Enhance_Base, Enhance_Plain):
|
||||
field_i = models.CharField(max_length=10)
|
||||
|
|
@ -51,7 +62,7 @@ class DiamondY(DiamondBase):
|
|||
class DiamondXY(DiamondX, DiamondY):
|
||||
pass
|
||||
|
||||
class RelationBase(ShowFieldsAndTypes, PolymorphicModel):
|
||||
class RelationBase(ShowFieldTypeAndContent, PolymorphicModel):
|
||||
field_base = models.CharField(max_length=10)
|
||||
fk = models.ForeignKey('self', null=True)
|
||||
m2m = models.ManyToManyField('self')
|
||||
|
|
@ -68,11 +79,11 @@ class RelatingModel(models.Model):
|
|||
class MyManager(PolymorphicManager):
|
||||
def get_query_set(self):
|
||||
return super(MyManager, self).get_query_set().order_by('-field1')
|
||||
class ModelWithMyManager(ShowFieldsAndTypes, Model2A):
|
||||
class ModelWithMyManager(ShowFieldTypeAndContent, Model2A):
|
||||
objects = MyManager()
|
||||
field4 = models.CharField(max_length=10)
|
||||
|
||||
class MROBase1(PolymorphicModel):
|
||||
class MROBase1(ShowFieldType, PolymorphicModel):
|
||||
objects = MyManager()
|
||||
field1 = models.CharField(max_length=10) # needed as MyManager uses it
|
||||
class MROBase2(MROBase1):
|
||||
|
|
@ -89,23 +100,23 @@ class MgrInheritA(models.Model):
|
|||
class MgrInheritB(MgrInheritA):
|
||||
mgrB = models.Manager()
|
||||
field2 = models.CharField(max_length=10)
|
||||
class MgrInheritC(ShowFieldsAndTypes, MgrInheritB):
|
||||
class MgrInheritC(ShowFieldTypeAndContent, MgrInheritB):
|
||||
pass
|
||||
|
||||
class BlogBase(ShowFieldsAndTypes, PolymorphicModel):
|
||||
class BlogBase(ShowFieldTypeAndContent, PolymorphicModel):
|
||||
name = models.CharField(max_length=10)
|
||||
class BlogA(BlogBase):
|
||||
info = models.CharField(max_length=10)
|
||||
class BlogB(BlogBase):
|
||||
pass
|
||||
class BlogA_Entry(ShowFieldsAndTypes, PolymorphicModel):
|
||||
class BlogEntry(ShowFieldTypeAndContent, PolymorphicModel):
|
||||
blog = models.ForeignKey(BlogA)
|
||||
text = models.CharField(max_length=10)
|
||||
|
||||
class ModelFieldNameTest(PolymorphicModel):
|
||||
class ModelFieldNameTest(ShowFieldType, PolymorphicModel):
|
||||
modelfieldnametest = models.CharField(max_length=10)
|
||||
|
||||
class InitTestModel(PolymorphicModel):
|
||||
class InitTestModel(ShowFieldType, PolymorphicModel):
|
||||
bar = models.CharField(max_length=100)
|
||||
def __init__(self, *args, **kwargs):
|
||||
kwargs['bar'] = self.x()
|
||||
|
|
@ -115,13 +126,13 @@ class InitTestModelSubclass(InitTestModel):
|
|||
return 'XYZ'
|
||||
|
||||
# test bad field name
|
||||
#class TestBadFieldModel(PolymorphicModel):
|
||||
#class TestBadFieldModel(ShowFieldType, PolymorphicModel):
|
||||
# instance_of = models.CharField(max_length=10)
|
||||
|
||||
# validation error: "polymorphic.relatednameclash: Accessor for field 'polymorphic_ctype' clashes
|
||||
# with related field 'ContentType.relatednameclash_set'." (reported by Andrew Ingram)
|
||||
# fixed with related_name
|
||||
class RelatedNameClash(PolymorphicModel):
|
||||
class RelatedNameClash(ShowFieldType, PolymorphicModel):
|
||||
ctype = models.ForeignKey(ContentType, null=True, editable=False)
|
||||
|
||||
|
||||
|
|
@ -135,22 +146,29 @@ class testclass(TestCase):
|
|||
if o.field_b != 'b': print '# Django model inheritance diamond problem detected'
|
||||
|
||||
def test_annotate_aggregate_order(self):
|
||||
from django.db.models import Count
|
||||
|
||||
BlogA.objects.all().delete()
|
||||
# create a blog of type BlogA
|
||||
blog = BlogA.objects.create(name='B1', info='i1')
|
||||
entry1 = blog.bloga_entry_set.create(text='bla')
|
||||
entry2 = BlogA_Entry.objects.create(blog=blog, text='bla2')
|
||||
# create two blog entries in BlogA
|
||||
entry1 = blog.blogentry_set.create(text='bla')
|
||||
entry2 = BlogEntry.objects.create(blog=blog, text='bla2')
|
||||
|
||||
# create some BlogB to make the table more diverse
|
||||
# create some blogs of type BlogB to make the BlogBase table data really polymorphic
|
||||
o = BlogB.objects.create(name='Bb1')
|
||||
o = BlogB.objects.create(name='Bb2')
|
||||
o = BlogB.objects.create(name='Bb3')
|
||||
|
||||
qs = BlogBase.objects.annotate(entrycount=Count('BlogA___bloga_entry'))
|
||||
assert qs[0].entrycount == 2
|
||||
qs = BlogBase.objects.annotate(entrycount=Count('BlogA___blogentry'))
|
||||
|
||||
x = BlogBase.objects.aggregate(entrycount=Count('BlogA___bloga_entry'))
|
||||
assert len(qs)==4
|
||||
|
||||
for o in qs:
|
||||
if o.name=='B1':
|
||||
assert o.entrycount == 2
|
||||
else:
|
||||
assert o.entrycount == 0
|
||||
|
||||
x = BlogBase.objects.aggregate(entrycount=Count('BlogA___blogentry'))
|
||||
assert x['entrycount'] == 2
|
||||
|
||||
# create some more blogs for next test
|
||||
|
|
@ -159,7 +177,8 @@ class testclass(TestCase):
|
|||
b2 = BlogA.objects.create(name='B4', info='i4')
|
||||
b2 = BlogA.objects.create(name='B5', info='i5')
|
||||
|
||||
# test ordering
|
||||
### test ordering for field in all entries
|
||||
|
||||
expected = '''
|
||||
[ <BlogB: id 4, name (CharField): "Bb3">,
|
||||
<BlogB: id 3, name (CharField): "Bb2">,
|
||||
|
|
@ -171,8 +190,11 @@ class testclass(TestCase):
|
|||
<BlogA: id 1, name (CharField): "B1", info (CharField): "i1"> ]'''
|
||||
x = '\n' + repr(BlogBase.objects.order_by('-name'))
|
||||
assert x == expected
|
||||
|
||||
expected='''
|
||||
|
||||
### test ordering for field in one subclass only
|
||||
|
||||
# MySQL and SQLite return this order
|
||||
expected1='''
|
||||
[ <BlogA: id 8, name (CharField): "B5", info (CharField): "i5">,
|
||||
<BlogA: id 7, name (CharField): "B4", info (CharField): "i4">,
|
||||
<BlogA: id 6, name (CharField): "B3", info (CharField): "i3">,
|
||||
|
|
@ -181,8 +203,20 @@ class testclass(TestCase):
|
|||
<BlogB: id 2, name (CharField): "Bb1">,
|
||||
<BlogB: id 3, name (CharField): "Bb2">,
|
||||
<BlogB: id 4, name (CharField): "Bb3"> ]'''
|
||||
|
||||
# PostgreSQL returns this order
|
||||
expected2='''
|
||||
[ <BlogB: id 2, name (CharField): "Bb1">,
|
||||
<BlogB: id 3, name (CharField): "Bb2">,
|
||||
<BlogB: id 4, name (CharField): "Bb3">,
|
||||
<BlogA: id 8, name (CharField): "B5", info (CharField): "i5">,
|
||||
<BlogA: id 7, name (CharField): "B4", info (CharField): "i4">,
|
||||
<BlogA: id 6, name (CharField): "B3", info (CharField): "i3">,
|
||||
<BlogA: id 5, name (CharField): "B2", info (CharField): "i2">,
|
||||
<BlogA: id 1, name (CharField): "B1", info (CharField): "i1"> ]'''
|
||||
|
||||
x = '\n' + repr(BlogBase.objects.order_by('-BlogA___info'))
|
||||
assert x == expected
|
||||
assert x == expected1 or x == expected2
|
||||
|
||||
#assert False
|
||||
|
||||
|
|
@ -196,6 +230,7 @@ __test__ = {"doctest": """
|
|||
>>> get_version()
|
||||
'0.5 beta'
|
||||
|
||||
|
||||
### simple inheritance
|
||||
|
||||
>>> o=Model2A.objects.create(field1='A1')
|
||||
|
|
@ -212,6 +247,32 @@ __test__ = {"doctest": """
|
|||
>>> o.get_real_instance()
|
||||
<Model2C: id 3, field1 (CharField), field2 (CharField), field3 (CharField)>
|
||||
|
||||
|
||||
### ShowFieldContent, ShowFieldType, ShowFieldTypeAndContent, also with annotate()
|
||||
|
||||
>>> o=ModelShow1.objects.create(field1='abc')
|
||||
>>> o.m2m.add(o) ; o.save()
|
||||
>>> ModelShow1.objects.all()
|
||||
[ <ModelShow1: id 1, field1 (CharField), m2m (ManyToManyField)> ]
|
||||
|
||||
>>> o=ModelShow2.objects.create(field1='abc')
|
||||
>>> o.m2m.add(o) ; o.save()
|
||||
>>> ModelShow2.objects.all()
|
||||
[ <ModelShow2: id 1, field1: "abc", m2m: 1> ]
|
||||
|
||||
>>> o=ModelShow3.objects.create(field1='abc')
|
||||
>>> o.m2m.add(o) ; o.save()
|
||||
>>> ModelShow3.objects.all()
|
||||
[ <ModelShow3: id 1, field1 (CharField): "abc", m2m (ManyToManyField): 1> ]
|
||||
|
||||
>>> ModelShow1.objects.all().annotate(Count('m2m'))
|
||||
[ <ModelShow1: id 1, field1 (CharField), m2m (ManyToManyField) - Ann: m2m__count (int)> ]
|
||||
>>> ModelShow2.objects.all().annotate(Count('m2m'))
|
||||
[ <ModelShow2: id 1, field1: "abc", m2m: 1 - Ann: m2m__count: "1"> ]
|
||||
>>> ModelShow3.objects.all().annotate(Count('m2m'))
|
||||
[ <ModelShow3: id 1, field1 (CharField): "abc", m2m (ManyToManyField): 1 - Ann: m2m__count (int): "1"> ]
|
||||
|
||||
|
||||
### extra() method
|
||||
|
||||
>>> Model2A.objects.extra(where=['id IN (2, 3)'])
|
||||
|
|
@ -222,6 +283,7 @@ __test__ = {"doctest": """
|
|||
[ <Model2B: id 2, field1 (CharField), field2 (CharField)>,
|
||||
<Model2C: id 3, field1 (CharField), field2 (CharField), field3 (CharField)> ]
|
||||
|
||||
|
||||
### class filtering, instance_of, not_instance_of
|
||||
|
||||
>>> Model2A.objects.instance_of(Model2B)
|
||||
|
|
@ -246,6 +308,7 @@ __test__ = {"doctest": """
|
|||
[ <Model2B: id 2, field1 (CharField), field2 (CharField)>,
|
||||
<Model2C: id 3, field1 (CharField), field2 (CharField), field3 (CharField)> ]
|
||||
|
||||
|
||||
### get & delete
|
||||
|
||||
>>> oa=Model2A.objects.get(id=2)
|
||||
|
|
@ -257,6 +320,7 @@ __test__ = {"doctest": """
|
|||
[ <Model2A: id 1, field1 (CharField)>,
|
||||
<Model2C: id 3, field1 (CharField), field2 (CharField), field3 (CharField)> ]
|
||||
|
||||
|
||||
### queryset combining
|
||||
|
||||
>>> o=ModelX.objects.create(field_x='x')
|
||||
|
|
@ -266,6 +330,7 @@ __test__ = {"doctest": """
|
|||
[ <ModelX: id 1, field_b (CharField), field_x (CharField)>,
|
||||
<ModelY: id 2, field_b (CharField), field_y (CharField)> ]
|
||||
|
||||
|
||||
### multiple inheritance, subclassing third party models (mix PolymorphicModel with models.Model)
|
||||
|
||||
>>> o = Enhance_Base.objects.create(field_b='b-base')
|
||||
|
|
@ -275,6 +340,7 @@ __test__ = {"doctest": """
|
|||
[ <Enhance_Base: id 1, field_b (CharField): "b-base">,
|
||||
<Enhance_Inherit: id 2, field_b (CharField): "b-inherit", field_p (CharField): "p", field_i (CharField): "i"> ]
|
||||
|
||||
|
||||
### ForeignKey, ManyToManyField
|
||||
|
||||
>>> obase=RelationBase.objects.create(field_base='base')
|
||||
|
|
@ -284,27 +350,27 @@ __test__ = {"doctest": """
|
|||
>>> oa.m2m.add(oa); oa.m2m.add(ob)
|
||||
|
||||
>>> RelationBase.objects.all()
|
||||
[ <RelationBase: id 1, field_base (CharField): "base", fk (ForeignKey): "None">,
|
||||
<RelationA: id 2, field_base (CharField): "A1", fk (ForeignKey): "RelationBase", field_a (CharField): "A2">,
|
||||
<RelationB: id 3, field_base (CharField): "B1", fk (ForeignKey): "RelationA", field_b (CharField): "B2">,
|
||||
<RelationBC: id 4, field_base (CharField): "C1", fk (ForeignKey): "RelationA", field_b (CharField): "C2", field_c (CharField): "C3"> ]
|
||||
[ <RelationBase: id 1, field_base (CharField): "base", fk (ForeignKey): "None", m2m (ManyToManyField): 0>,
|
||||
<RelationA: id 2, field_base (CharField): "A1", fk (ForeignKey): "RelationBase", field_a (CharField): "A2", m2m (ManyToManyField): 2>,
|
||||
<RelationB: id 3, field_base (CharField): "B1", fk (ForeignKey): "RelationA", field_b (CharField): "B2", m2m (ManyToManyField): 1>,
|
||||
<RelationBC: id 4, field_base (CharField): "C1", fk (ForeignKey): "RelationA", field_b (CharField): "C2", field_c (CharField): "C3", m2m (ManyToManyField): 0> ]
|
||||
|
||||
>>> oa=RelationBase.objects.get(id=2)
|
||||
>>> oa.fk
|
||||
<RelationBase: id 1, field_base (CharField): "base", fk (ForeignKey): "None">
|
||||
<RelationBase: id 1, field_base (CharField): "base", fk (ForeignKey): "None", m2m (ManyToManyField): 0>
|
||||
|
||||
>>> oa.relationbase_set.all()
|
||||
[ <RelationB: id 3, field_base (CharField): "B1", fk (ForeignKey): "RelationA", field_b (CharField): "B2">,
|
||||
<RelationBC: id 4, field_base (CharField): "C1", fk (ForeignKey): "RelationA", field_b (CharField): "C2", field_c (CharField): "C3"> ]
|
||||
[ <RelationB: id 3, field_base (CharField): "B1", fk (ForeignKey): "RelationA", field_b (CharField): "B2", m2m (ManyToManyField): 1>,
|
||||
<RelationBC: id 4, field_base (CharField): "C1", fk (ForeignKey): "RelationA", field_b (CharField): "C2", field_c (CharField): "C3", m2m (ManyToManyField): 0> ]
|
||||
|
||||
>>> ob=RelationBase.objects.get(id=3)
|
||||
>>> ob.fk
|
||||
<RelationA: id 2, field_base (CharField): "A1", fk (ForeignKey): "RelationBase", field_a (CharField): "A2">
|
||||
<RelationA: id 2, field_base (CharField): "A1", fk (ForeignKey): "RelationBase", field_a (CharField): "A2", m2m (ManyToManyField): 2>
|
||||
|
||||
>>> oa=RelationA.objects.get()
|
||||
>>> oa.m2m.all()
|
||||
[ <RelationA: id 2, field_base (CharField): "A1", fk (ForeignKey): "RelationBase", field_a (CharField): "A2">,
|
||||
<RelationB: id 3, field_base (CharField): "B1", fk (ForeignKey): "RelationA", field_b (CharField): "B2"> ]
|
||||
[ <RelationA: id 2, field_base (CharField): "A1", fk (ForeignKey): "RelationBase", field_a (CharField): "A2", m2m (ManyToManyField): 2>,
|
||||
<RelationB: id 3, field_base (CharField): "B1", fk (ForeignKey): "RelationA", field_b (CharField): "B2", m2m (ManyToManyField): 1> ]
|
||||
|
||||
### user-defined manager
|
||||
|
||||
|
|
@ -320,6 +386,7 @@ __test__ = {"doctest": """
|
|||
>>> type(ModelWithMyManager._default_manager)
|
||||
<class 'polymorphic.tests.MyManager'>
|
||||
|
||||
|
||||
### Manager Inheritance
|
||||
|
||||
>>> type(MRODerived.objects) # MRO
|
||||
|
|
@ -333,10 +400,12 @@ __test__ = {"doctest": """
|
|||
>>> type(MROBase2._default_manager)
|
||||
<class 'polymorphic.tests.MyManager'>
|
||||
|
||||
|
||||
### fixed issue in PolymorphicModel.__getattribute__: field name same as model name
|
||||
>>> ModelFieldNameTest.objects.create(modelfieldnametest='1')
|
||||
<ModelFieldNameTest: id 1, modelfieldnametest (CharField)>
|
||||
|
||||
|
||||
### fixed issue in PolymorphicModel.__getattribute__:
|
||||
# if subclass defined __init__ and accessed class members, __getattribute__ had a problem: "...has no attribute 'sub_and_superclass_dict'"
|
||||
#>>> o
|
||||
|
|
@ -344,6 +413,7 @@ __test__ = {"doctest": """
|
|||
>>> o.bar
|
||||
'XYZ'
|
||||
|
||||
|
||||
### Django model inheritance diamond problem, fails for Django 1.1
|
||||
|
||||
#>>> o=DiamondXY.objects.create(field_b='b', field_x='x', field_y='y')
|
||||
|
|
|
|||
Loading…
Reference in New Issue