PageRenderTime 40ms CodeModel.GetById 2ms app.highlight 29ms RepoModel.GetById 1ms app.codeStats 1ms

/polymorphic/tests.py

https://bitbucket.org/bconstantin/django_polymorphic/
Python | 639 lines | 574 code | 47 blank | 18 comment | 11 complexity | e21ee72a316fae161b6e6de0466ad7f6 MD5 | raw file
  1# -*- coding: utf-8 -*-
  2""" Test Cases
  3    Please see README.rst or DOCS.rst or http://bserve.webhop.org/wiki/django_polymorphic
  4"""
  5
  6import settings
  7import sys
  8from pprint import pprint
  9
 10from django import VERSION as django_VERSION
 11from django.test import TestCase
 12from django.db.models.query import QuerySet
 13from django.db.models import Q,Count
 14from django.db import models
 15from django.contrib.contenttypes.models import ContentType
 16
 17from polymorphic import PolymorphicModel, PolymorphicManager, PolymorphicQuerySet
 18from polymorphic import ShowFieldContent, ShowFieldType, ShowFieldTypeAndContent, get_version
 19from polymorphic import translate_polymorphic_Q_object
 20
 21class PlainA(models.Model):
 22    field1 = models.CharField(max_length=10)
 23class PlainB(PlainA):
 24    field2 = models.CharField(max_length=10)
 25class PlainC(PlainB):
 26    field3 = models.CharField(max_length=10)
 27
 28class Model2A(ShowFieldType, PolymorphicModel):
 29    field1 = models.CharField(max_length=10)
 30class Model2B(Model2A):
 31    field2 = models.CharField(max_length=10)
 32class Model2C(Model2B):
 33    field3 = models.CharField(max_length=10)
 34class Model2D(Model2C):
 35    field4 = models.CharField(max_length=10)
 36
 37class ModelExtraA(ShowFieldTypeAndContent, PolymorphicModel):
 38    field1 = models.CharField(max_length=10)
 39class ModelExtraB(ModelExtraA):
 40    field2 = models.CharField(max_length=10)
 41class ModelExtraC(ModelExtraB):
 42    field3 = models.CharField(max_length=10)
 43class ModelExtraExternal(models.Model):
 44    topic = models.CharField(max_length=10)
 45
 46class ModelShow1(ShowFieldType,PolymorphicModel):
 47    field1 = models.CharField(max_length=10)
 48    m2m = models.ManyToManyField('self')
 49class ModelShow2(ShowFieldContent, PolymorphicModel):
 50    field1 = models.CharField(max_length=10)
 51    m2m = models.ManyToManyField('self')
 52class ModelShow3(ShowFieldTypeAndContent, PolymorphicModel):
 53    field1 = models.CharField(max_length=10)
 54    m2m = models.ManyToManyField('self')
 55
 56class ModelShow1_plain(PolymorphicModel):
 57    field1 = models.CharField(max_length=10)
 58class ModelShow2_plain(ModelShow1_plain):
 59    field2 = models.CharField(max_length=10)
 60
 61
 62class Base(ShowFieldType, PolymorphicModel):
 63    field_b = models.CharField(max_length=10)
 64class ModelX(Base):
 65    field_x = models.CharField(max_length=10)
 66class ModelY(Base):
 67    field_y = models.CharField(max_length=10)
 68
 69class Enhance_Plain(models.Model):
 70    field_p = models.CharField(max_length=10)
 71class Enhance_Base(ShowFieldTypeAndContent, PolymorphicModel):
 72    field_b = models.CharField(max_length=10)
 73class Enhance_Inherit(Enhance_Base, Enhance_Plain):
 74    field_i = models.CharField(max_length=10)
 75
 76class DiamondBase(models.Model):
 77    field_b = models.CharField(max_length=10)
 78class DiamondX(DiamondBase):
 79    field_x = models.CharField(max_length=10)
 80class DiamondY(DiamondBase):
 81    field_y = models.CharField(max_length=10)
 82class DiamondXY(DiamondX, DiamondY):
 83    pass
 84
 85class RelationBase(ShowFieldTypeAndContent, PolymorphicModel):
 86    field_base = models.CharField(max_length=10)
 87    fk = models.ForeignKey('self', null=True)
 88    m2m = models.ManyToManyField('self')
 89class RelationA(RelationBase):
 90    field_a = models.CharField(max_length=10)
 91class RelationB(RelationBase):
 92    field_b = models.CharField(max_length=10)
 93class RelationBC(RelationB):
 94    field_c = models.CharField(max_length=10)
 95
 96class RelatingModel(models.Model):
 97    many2many = models.ManyToManyField(Model2A)
 98
 99class One2OneRelatingModel(PolymorphicModel):
100    one2one = models.OneToOneField(Model2A)
101    field1 = models.CharField(max_length=10)
102
103class One2OneRelatingModelDerived(One2OneRelatingModel):
104    field2 = models.CharField(max_length=10)
105
106class MyManager(PolymorphicManager):
107    def get_query_set(self):
108        return super(MyManager, self).get_query_set().order_by('-field1')
109class ModelWithMyManager(ShowFieldTypeAndContent, Model2A):
110    objects = MyManager()
111    field4 = models.CharField(max_length=10)
112
113class MROBase1(ShowFieldType, PolymorphicModel):
114    objects = MyManager()
115    field1 = models.CharField(max_length=10) # needed as MyManager uses it
116class MROBase2(MROBase1):
117    pass # Django vanilla inheritance does not inherit MyManager as _default_manager here
118class MROBase3(models.Model):
119    objects = PolymorphicManager()
120class MRODerived(MROBase2, MROBase3):
121    pass
122
123class MgrInheritA(models.Model):
124    mgrA = models.Manager()
125    mgrA2 = models.Manager()
126    field1 = models.CharField(max_length=10)
127class MgrInheritB(MgrInheritA):
128    mgrB = models.Manager()
129    field2 = models.CharField(max_length=10)
130class MgrInheritC(ShowFieldTypeAndContent, MgrInheritB):
131    pass
132
133class BlogBase(ShowFieldTypeAndContent, PolymorphicModel):
134    name = models.CharField(max_length=10)
135class BlogA(BlogBase):
136    info = models.CharField(max_length=10)
137class BlogB(BlogBase):
138    pass
139class BlogEntry(ShowFieldTypeAndContent, PolymorphicModel):
140    blog = models.ForeignKey(BlogA)
141    text = models.CharField(max_length=10)
142
143class BlogEntry_limit_choices_to(ShowFieldTypeAndContent, PolymorphicModel):
144    blog = models.ForeignKey(BlogBase)
145    text = models.CharField(max_length=10)
146
147class ModelFieldNameTest(ShowFieldType, PolymorphicModel):
148    modelfieldnametest = models.CharField(max_length=10)
149
150class InitTestModel(ShowFieldType, PolymorphicModel):
151    bar = models.CharField(max_length=100)
152    def __init__(self, *args, **kwargs):
153        kwargs['bar'] = self.x()
154        super(InitTestModel, self).__init__(*args, **kwargs)
155class InitTestModelSubclass(InitTestModel):
156    def x(self):
157        return 'XYZ'
158
159# models from github issue
160class Top(PolymorphicModel):
161    name = models.CharField(max_length=50)
162class Middle(Top):
163    description = models.TextField()
164class Bottom(Middle):
165    author = models.CharField(max_length=50)
166
167
168# UUID tests won't work with Django 1.1
169if not (django_VERSION[0] <= 1 and django_VERSION[1] <= 1):
170    try: from polymorphic.tools_for_tests  import UUIDField
171    except: pass
172    if 'UUIDField' in globals():
173        import uuid
174
175        class UUIDProject(ShowFieldTypeAndContent, PolymorphicModel):
176                uuid_primary_key = UUIDField(primary_key = True)
177                topic = models.CharField(max_length = 30)
178        class UUIDArtProject(UUIDProject):
179                artist = models.CharField(max_length = 30)
180        class UUIDResearchProject(UUIDProject):
181                supervisor = models.CharField(max_length = 30)
182
183        class UUIDPlainA(models.Model):
184            uuid_primary_key = UUIDField(primary_key = True)
185            field1 = models.CharField(max_length=10)
186        class UUIDPlainB(UUIDPlainA):
187            field2 = models.CharField(max_length=10)
188        class UUIDPlainC(UUIDPlainB):
189            field3 = models.CharField(max_length=10)
190
191
192# test bad field name
193#class TestBadFieldModel(ShowFieldType, PolymorphicModel):
194#    instance_of = models.CharField(max_length=10)
195
196# validation error: "polymorphic.relatednameclash: Accessor for field 'polymorphic_ctype' clashes
197# with related field 'ContentType.relatednameclash_set'." (reported by Andrew Ingram)
198# fixed with related_name
199class RelatedNameClash(ShowFieldType, PolymorphicModel):
200    ctype = models.ForeignKey(ContentType, null=True, editable=False)
201
202
203class testclass(TestCase):
204    def test_diamond_inheritance(self):
205        # Django diamond problem
206        o = DiamondXY.objects.create(field_b='b', field_x='x', field_y='y')
207        print 'DiamondXY fields 1: field_b "%s", field_x "%s", field_y "%s"' % (o.field_b, o.field_x, o.field_y)
208        o = DiamondXY.objects.get()
209        print 'DiamondXY fields 2: field_b "%s", field_x "%s", field_y "%s"' % (o.field_b, o.field_x, o.field_y)
210        if o.field_b != 'b':
211            print
212            print '# known django model inheritance diamond problem detected'
213
214    def test_annotate_aggregate_order(self):
215
216        # create a blog of type BlogA
217        blog = BlogA.objects.create(name='B1', info='i1')
218        # create two blog entries in BlogA
219        entry1 = blog.blogentry_set.create(text='bla')
220        entry2 = BlogEntry.objects.create(blog=blog, text='bla2')
221
222        # create some blogs of type BlogB to make the BlogBase table data really polymorphic
223        o = BlogB.objects.create(name='Bb1')
224        o = BlogB.objects.create(name='Bb2')
225        o = BlogB.objects.create(name='Bb3')
226
227        qs = BlogBase.objects.annotate(entrycount=Count('BlogA___blogentry'))
228
229        assert len(qs)==4
230
231        for o in qs:
232            if o.name=='B1':
233                assert o.entrycount == 2
234            else:
235                assert o.entrycount == 0
236
237        x = BlogBase.objects.aggregate(entrycount=Count('BlogA___blogentry'))
238        assert x['entrycount'] == 2
239
240        # create some more blogs for next test
241        b2 = BlogA.objects.create(name='B2', info='i2')
242        b2 = BlogA.objects.create(name='B3', info='i3')
243        b2 = BlogA.objects.create(name='B4', info='i4')
244        b2 = BlogA.objects.create(name='B5', info='i5')
245
246        ### test ordering for field in all entries
247
248        expected = '''
249[ <BlogB: id 4, name (CharField) "Bb3">,
250  <BlogB: id 3, name (CharField) "Bb2">,
251  <BlogB: id 2, name (CharField) "Bb1">,
252  <BlogA: id 8, name (CharField) "B5", info (CharField) "i5">,
253  <BlogA: id 7, name (CharField) "B4", info (CharField) "i4">,
254  <BlogA: id 6, name (CharField) "B3", info (CharField) "i3">,
255  <BlogA: id 5, name (CharField) "B2", info (CharField) "i2">,
256  <BlogA: id 1, name (CharField) "B1", info (CharField) "i1"> ]'''
257        x = '\n' + repr(BlogBase.objects.order_by('-name'))
258        assert x == expected
259
260        ### test ordering for field in one subclass only
261
262        # MySQL and SQLite return this order
263        expected1='''
264[ <BlogA: id 8, name (CharField) "B5", info (CharField) "i5">,
265  <BlogA: id 7, name (CharField) "B4", info (CharField) "i4">,
266  <BlogA: id 6, name (CharField) "B3", info (CharField) "i3">,
267  <BlogA: id 5, name (CharField) "B2", info (CharField) "i2">,
268  <BlogA: id 1, name (CharField) "B1", info (CharField) "i1">,
269  <BlogB: id 2, name (CharField) "Bb1">,
270  <BlogB: id 3, name (CharField) "Bb2">,
271  <BlogB: id 4, name (CharField) "Bb3"> ]'''
272
273        # PostgreSQL returns this order
274        expected2='''
275[ <BlogB: id 2, name (CharField) "Bb1">,
276  <BlogB: id 3, name (CharField) "Bb2">,
277  <BlogB: id 4, name (CharField) "Bb3">,
278  <BlogA: id 8, name (CharField) "B5", info (CharField) "i5">,
279  <BlogA: id 7, name (CharField) "B4", info (CharField) "i4">,
280  <BlogA: id 6, name (CharField) "B3", info (CharField) "i3">,
281  <BlogA: id 5, name (CharField) "B2", info (CharField) "i2">,
282  <BlogA: id 1, name (CharField) "B1", info (CharField) "i1"> ]'''
283
284        x = '\n' + repr(BlogBase.objects.order_by('-BlogA___info'))
285        assert x == expected1 or x == expected2
286
287
288    def test_limit_choices_to(self):
289        "this is not really a testcase, as limit_choices_to only affects the Django admin"
290        # create a blog of type BlogA
291        blog_a = BlogA.objects.create(name='aa', info='aa')
292        blog_b = BlogB.objects.create(name='bb')
293        # create two blog entries
294        entry1 = BlogEntry_limit_choices_to.objects.create(blog=blog_b, text='bla2')
295        entry2 = BlogEntry_limit_choices_to.objects.create(blog=blog_b, text='bla2')
296
297
298    def test_primary_key_custom_field_problem(self):
299        "object retrieval problem occuring with some custom primary key fields (UUIDField as test case)"
300        if not 'UUIDField' in globals(): return
301        a=UUIDProject.objects.create(topic="John's gathering")
302        b=UUIDArtProject.objects.create(topic="Sculpting with Tim", artist="T. Turner")
303        c=UUIDResearchProject.objects.create(topic="Swallow Aerodynamics", supervisor="Dr. Winter")
304        qs=UUIDProject.objects.all()
305        ol=list(qs)
306        a=qs[0]
307        b=qs[1]
308        c=qs[2]
309        assert len(qs)==3
310        assert type(a.uuid_primary_key)==uuid.UUID and type(a.pk)==uuid.UUID
311        res=repr(qs)
312        import re
313        res=re.sub(' "(.*?)..", topic',', topic',res)
314        res_exp="""[ <UUIDProject: uuid_primary_key (UUIDField/pk), topic (CharField) "John's gathering">,
315  <UUIDArtProject: uuid_primary_key (UUIDField/pk), topic (CharField) "Sculpting with Tim", artist (CharField) "T. Turner">,
316  <UUIDResearchProject: uuid_primary_key (UUIDField/pk), topic (CharField) "Swallow Aerodynamics", supervisor (CharField) "Dr. Winter"> ]"""
317        assert res==res_exp, res
318        #if (a.pk!= uuid.UUID or c.pk!= uuid.UUID):
319        #    print
320        #    print '# known inconstency with custom primary key field detected (django problem?)'
321
322        a=UUIDPlainA.objects.create(field1='A1')
323        b=UUIDPlainB.objects.create(field1='B1', field2='B2')
324        c=UUIDPlainC.objects.create(field1='C1', field2='C2', field3='C3')
325        qs=UUIDPlainA.objects.all()
326        if (a.pk!= uuid.UUID or c.pk!= uuid.UUID):
327            print
328            print '# known type inconstency with custom primary key field detected (django problem?)'
329
330
331def show_base_manager(model):
332    print type(model._base_manager),model._base_manager.model
333
334__test__ = {"doctest": """
335#######################################################
336### Tests
337
338>>> settings.DEBUG=True
339
340
341### simple inheritance
342
343>>> o=Model2A.objects.create(field1='A1')
344>>> o=Model2B.objects.create(field1='B1', field2='B2')
345>>> o=Model2C.objects.create(field1='C1', field2='C2', field3='C3')
346>>> o=Model2D.objects.create(field1='D1', field2='D2', field3='D3', field4='D4')
347>>> Model2A.objects.all()
348[ <Model2A: id 1, field1 (CharField)>,
349  <Model2B: id 2, field1 (CharField), field2 (CharField)>,
350  <Model2C: id 3, field1 (CharField), field2 (CharField), field3 (CharField)>,
351  <Model2D: id 4, field1 (CharField), field2 (CharField), field3 (CharField), field4 (CharField)> ]
352
353# manual get_real_instance()
354>>> o=Model2A.objects.non_polymorphic().get(field1='C1')
355>>> o.get_real_instance()
356<Model2C: id 3, field1 (CharField), field2 (CharField), field3 (CharField)>
357
358# non_polymorphic()
359>>> qs=Model2A.objects.all().non_polymorphic()
360>>> qs
361[ <Model2A: id 1, field1 (CharField)>,
362  <Model2A: id 2, field1 (CharField)>,
363  <Model2A: id 3, field1 (CharField)>,
364  <Model2A: id 4, field1 (CharField)> ]
365
366# get_real_instances()
367>>> qs.get_real_instances()
368[ <Model2A: id 1, field1 (CharField)>,
369  <Model2B: id 2, field1 (CharField), field2 (CharField)>,
370  <Model2C: id 3, field1 (CharField), field2 (CharField), field3 (CharField)>,
371  <Model2D: id 4, field1 (CharField), field2 (CharField), field3 (CharField), field4 (CharField)> ]
372
373>>> l=list(qs)
374>>> Model2A.objects.get_real_instances(l)
375[ <Model2A: id 1, field1 (CharField)>,
376  <Model2B: id 2, field1 (CharField), field2 (CharField)>,
377  <Model2C: id 3, field1 (CharField), field2 (CharField), field3 (CharField)>,
378  <Model2D: id 4, field1 (CharField), field2 (CharField), field3 (CharField), field4 (CharField)> ]
379
380# translate_polymorphic_Q_object
381>>> q=Model2A.translate_polymorphic_Q_object( Q(instance_of=Model2C) )
382>>> Model2A.objects.filter(q)
383[ <Model2C: id 3, field1 (CharField), field2 (CharField), field3 (CharField)>,
384  <Model2D: id 4, field1 (CharField), field2 (CharField), field3 (CharField), field4 (CharField)> ]
385
386
387### test inheritance pointers & _base_managers
388
389>>> show_base_manager(PlainA)
390<class 'django.db.models.manager.Manager'> <class 'polymorphic.tests.PlainA'>
391>>> show_base_manager(PlainB)
392<class 'django.db.models.manager.Manager'> <class 'polymorphic.tests.PlainB'>
393>>> show_base_manager(PlainC)
394<class 'django.db.models.manager.Manager'> <class 'polymorphic.tests.PlainC'>
395>>> show_base_manager(Model2A)
396<class 'polymorphic.manager.PolymorphicManager'> <class 'polymorphic.tests.Model2A'>
397>>> show_base_manager(Model2B)
398<class 'django.db.models.manager.Manager'> <class 'polymorphic.tests.Model2B'>
399>>> show_base_manager(Model2C)
400<class 'django.db.models.manager.Manager'> <class 'polymorphic.tests.Model2C'>
401>>> show_base_manager(One2OneRelatingModel)
402<class 'polymorphic.manager.PolymorphicManager'> <class 'polymorphic.tests.One2OneRelatingModel'>
403>>> show_base_manager(One2OneRelatingModelDerived)
404<class 'django.db.models.manager.Manager'> <class 'polymorphic.tests.One2OneRelatingModelDerived'>
405
406>>> o=Model2A.base_objects.get(field1='C1')
407>>> o.model2b
408<Model2B: id 3, field1 (CharField), field2 (CharField)>
409
410>>> o=Model2B.base_objects.get(field1='C1')
411>>> o.model2c
412<Model2C: id 3, field1 (CharField), field2 (CharField), field3 (CharField)>
413
414
415### OneToOneField, test both directions for polymorphism
416
417>>> a=Model2A.base_objects.get(field1='C1')
418>>> b=One2OneRelatingModelDerived.objects.create(one2one=a, field1='f1', field2='f2')
419>>> b.one2one  # this result is basically wrong, probably due to Django cacheing (we used base_objects), but should not be a problem
420<Model2A: id 3, field1 (CharField)>
421>>> c=One2OneRelatingModelDerived.objects.get(field1='f1')
422>>> c.one2one
423<Model2C: id 3, field1 (CharField), field2 (CharField), field3 (CharField)>
424
425>>> a.one2onerelatingmodel
426<One2OneRelatingModelDerived: One2OneRelatingModelDerived object>
427
428
429### ShowFieldContent, ShowFieldType, ShowFieldTypeAndContent, also with annotate()
430
431>>> o=ModelShow1.objects.create(field1='abc')
432>>> o.m2m.add(o) ; o.save()
433>>> ModelShow1.objects.all()
434[ <ModelShow1: id 1, field1 (CharField), m2m (ManyToManyField)> ]
435
436>>> o=ModelShow2.objects.create(field1='abc')
437>>> o.m2m.add(o) ; o.save()
438>>> ModelShow2.objects.all()
439[ <ModelShow2: id 1, field1 "abc", m2m 1> ]
440
441>>> o=ModelShow3.objects.create(field1='abc')
442>>> o.m2m.add(o) ; o.save()
443>>> ModelShow3.objects.all()
444[ <ModelShow3: id 1, field1 (CharField) "abc", m2m (ManyToManyField) 1> ]
445
446>>> ModelShow1.objects.all().annotate(Count('m2m'))
447[ <ModelShow1: id 1, field1 (CharField), m2m (ManyToManyField) - Ann: m2m__count (int)> ]
448>>> ModelShow2.objects.all().annotate(Count('m2m'))
449[ <ModelShow2: id 1, field1 "abc", m2m 1 - Ann: m2m__count 1> ]
450>>> ModelShow3.objects.all().annotate(Count('m2m'))
451[ <ModelShow3: id 1, field1 (CharField) "abc", m2m (ManyToManyField) 1 - Ann: m2m__count (int) 1> ]
452
453# no pretty printing
454>>> o=ModelShow1_plain.objects.create(field1='abc')
455>>> o=ModelShow2_plain.objects.create(field1='abc', field2='def')
456>>> ModelShow1_plain.objects.all()
457[<ModelShow1_plain: ModelShow1_plain object>, <ModelShow2_plain: ModelShow2_plain object>]
458
459
460### extra() method
461
462>>> Model2A.objects.extra(where=['id IN (2, 3)'])
463[ <Model2B: id 2, field1 (CharField), field2 (CharField)>,
464  <Model2C: id 3, field1 (CharField), field2 (CharField), field3 (CharField)> ]
465
466>>> Model2A.objects.extra(select={"select_test": "field1 = 'A1'"}, where=["field1 = 'A1' OR field1 = 'B1'"], order_by = ['-id'] )
467[ <Model2B: id 2, field1 (CharField), field2 (CharField) - Extra: select_test (int)>,
468  <Model2A: id 1, field1 (CharField) - Extra: select_test (int)> ]
469
470>>> o=ModelExtraA.objects.create(field1='A1')
471>>> o=ModelExtraB.objects.create(field1='B1', field2='B2')
472>>> o=ModelExtraC.objects.create(field1='C1', field2='C2', field3='C3')
473>>> o=ModelExtraExternal.objects.create(topic='extra1')
474>>> o=ModelExtraExternal.objects.create(topic='extra2')
475>>> o=ModelExtraExternal.objects.create(topic='extra3')
476>>> ModelExtraA.objects.extra(tables=["polymorphic_modelextraexternal"], select={"topic":"polymorphic_modelextraexternal.topic"}, where=["polymorphic_modelextraa.id = polymorphic_modelextraexternal.id"] )
477[ <ModelExtraA: id 1, field1 (CharField) "A1" - Extra: topic (unicode) "extra1">,
478  <ModelExtraB: id 2, field1 (CharField) "B1", field2 (CharField) "B2" - Extra: topic (unicode) "extra2">,
479  <ModelExtraC: id 3, field1 (CharField) "C1", field2 (CharField) "C2", field3 (CharField) "C3" - Extra: topic (unicode) "extra3"> ]
480
481### class filtering, instance_of, not_instance_of
482
483>>> Model2A.objects.instance_of(Model2B)
484[ <Model2B: id 2, field1 (CharField), field2 (CharField)>,
485  <Model2C: id 3, field1 (CharField), field2 (CharField), field3 (CharField)>,
486  <Model2D: id 4, field1 (CharField), field2 (CharField), field3 (CharField), field4 (CharField)> ]
487
488>>> Model2A.objects.filter(instance_of=Model2B)
489[ <Model2B: id 2, field1 (CharField), field2 (CharField)>,
490  <Model2C: id 3, field1 (CharField), field2 (CharField), field3 (CharField)>,
491  <Model2D: id 4, field1 (CharField), field2 (CharField), field3 (CharField), field4 (CharField)> ]
492
493>>> Model2A.objects.filter(Q(instance_of=Model2B))
494[ <Model2B: id 2, field1 (CharField), field2 (CharField)>,
495  <Model2C: id 3, field1 (CharField), field2 (CharField), field3 (CharField)>,
496  <Model2D: id 4, field1 (CharField), field2 (CharField), field3 (CharField), field4 (CharField)> ]
497
498>>> Model2A.objects.not_instance_of(Model2B)
499[ <Model2A: id 1, field1 (CharField)> ]
500
501
502### polymorphic filtering
503
504>>> Model2A.objects.filter(  Q( Model2B___field2 = 'B2' )  |  Q( Model2C___field3 = 'C3' )  )
505[ <Model2B: id 2, field1 (CharField), field2 (CharField)>,
506  <Model2C: id 3, field1 (CharField), field2 (CharField), field3 (CharField)> ]
507
508
509### get & delete
510
511>>> oa=Model2A.objects.get(id=2)
512>>> oa
513<Model2B: id 2, field1 (CharField), field2 (CharField)>
514
515>>> oa.delete()
516>>> Model2A.objects.all()
517[ <Model2A: id 1, field1 (CharField)>,
518  <Model2C: id 3, field1 (CharField), field2 (CharField), field3 (CharField)>,
519  <Model2D: id 4, field1 (CharField), field2 (CharField), field3 (CharField), field4 (CharField)> ]
520
521
522### queryset combining
523
524>>> o=ModelX.objects.create(field_x='x')
525>>> o=ModelY.objects.create(field_y='y')
526
527>>> Base.objects.instance_of(ModelX) | Base.objects.instance_of(ModelY)
528[ <ModelX: id 1, field_b (CharField), field_x (CharField)>,
529  <ModelY: id 2, field_b (CharField), field_y (CharField)> ]
530
531
532### multiple inheritance, subclassing third party models (mix PolymorphicModel with models.Model)
533
534>>> o = Enhance_Base.objects.create(field_b='b-base')
535>>> o = Enhance_Inherit.objects.create(field_b='b-inherit', field_p='p', field_i='i')
536
537>>> Enhance_Base.objects.all()
538[ <Enhance_Base: id 1, field_b (CharField) "b-base">,
539  <Enhance_Inherit: id 2, field_b (CharField) "b-inherit", field_p (CharField) "p", field_i (CharField) "i"> ]
540
541
542### ForeignKey, ManyToManyField
543
544>>> obase=RelationBase.objects.create(field_base='base')
545>>> oa=RelationA.objects.create(field_base='A1', field_a='A2', fk=obase)
546>>> ob=RelationB.objects.create(field_base='B1', field_b='B2', fk=oa)
547>>> oc=RelationBC.objects.create(field_base='C1', field_b='C2', field_c='C3', fk=oa)
548>>> oa.m2m.add(oa); oa.m2m.add(ob)
549
550>>> RelationBase.objects.all()
551[ <RelationBase: id 1, field_base (CharField) "base", fk (ForeignKey) None, m2m (ManyToManyField) 0>,
552  <RelationA: id 2, field_base (CharField) "A1", fk (ForeignKey) RelationBase, field_a (CharField) "A2", m2m (ManyToManyField) 2>,
553  <RelationB: id 3, field_base (CharField) "B1", fk (ForeignKey) RelationA, field_b (CharField) "B2", m2m (ManyToManyField) 1>,
554  <RelationBC: id 4, field_base (CharField) "C1", fk (ForeignKey) RelationA, field_b (CharField) "C2", field_c (CharField) "C3", m2m (ManyToManyField) 0> ]
555
556>>> oa=RelationBase.objects.get(id=2)
557>>> oa.fk
558<RelationBase: id 1, field_base (CharField) "base", fk (ForeignKey) None, m2m (ManyToManyField) 0>
559
560>>> oa.relationbase_set.all()
561[ <RelationB: id 3, field_base (CharField) "B1", fk (ForeignKey) RelationA, field_b (CharField) "B2", m2m (ManyToManyField) 1>,
562  <RelationBC: id 4, field_base (CharField) "C1", fk (ForeignKey) RelationA, field_b (CharField) "C2", field_c (CharField) "C3", m2m (ManyToManyField) 0> ]
563
564>>> ob=RelationBase.objects.get(id=3)
565>>> ob.fk
566<RelationA: id 2, field_base (CharField) "A1", fk (ForeignKey) RelationBase, field_a (CharField) "A2", m2m (ManyToManyField) 2>
567
568>>> oa=RelationA.objects.get()
569>>> oa.m2m.all()
570[ <RelationA: id 2, field_base (CharField) "A1", fk (ForeignKey) RelationBase, field_a (CharField) "A2", m2m (ManyToManyField) 2>,
571  <RelationB: id 3, field_base (CharField) "B1", fk (ForeignKey) RelationA, field_b (CharField) "B2", m2m (ManyToManyField) 1> ]
572
573### user-defined manager
574
575>>> o=ModelWithMyManager.objects.create(field1='D1a', field4='D4a')
576>>> o=ModelWithMyManager.objects.create(field1='D1b', field4='D4b')
577
578>>> ModelWithMyManager.objects.all()
579[ <ModelWithMyManager: id 6, field1 (CharField) "D1b", field4 (CharField) "D4b">,
580  <ModelWithMyManager: id 5, field1 (CharField) "D1a", field4 (CharField) "D4a"> ]
581
582>>> type(ModelWithMyManager.objects)
583<class 'polymorphic.tests.MyManager'>
584>>> type(ModelWithMyManager._default_manager)
585<class 'polymorphic.tests.MyManager'>
586
587
588### Manager Inheritance
589
590>>> type(MRODerived.objects) # MRO
591<class 'polymorphic.tests.MyManager'>
592
593# check for correct default manager
594>>> type(MROBase1._default_manager)
595<class 'polymorphic.tests.MyManager'>
596
597# Django vanilla inheritance does not inherit MyManager as _default_manager here
598>>> type(MROBase2._default_manager)
599<class 'polymorphic.tests.MyManager'>
600
601
602### fixed issue in PolymorphicModel.__getattribute__: field name same as model name
603>>> ModelFieldNameTest.objects.create(modelfieldnametest='1')
604<ModelFieldNameTest: id 1, modelfieldnametest (CharField)>
605
606
607### fixed issue in PolymorphicModel.__getattribute__:
608# if subclass defined __init__ and accessed class members, __getattribute__ had a problem: "...has no attribute 'sub_and_superclass_dict'"
609#>>> o
610>>> o = InitTestModelSubclass.objects.create()
611>>> o.bar
612'XYZ'
613
614
615### Django model inheritance diamond problem, fails for Django 1.1
616
617#>>> o=DiamondXY.objects.create(field_b='b', field_x='x', field_y='y')
618#>>> print 'DiamondXY fields 1: field_b "%s", field_x "%s", field_y "%s"' % (o.field_b, o.field_x, o.field_y)
619#DiamondXY fields 1: field_b "a", field_x "x", field_y "y"
620
621# test for github issue
622>>> t = Top()
623>>> t.save()
624>>> m = Middle()
625>>> m.save()
626>>> b = Bottom()
627>>> b.save()
628>>> Top.objects.all()
629[<Top: Top object>, <Middle: Middle object>, <Bottom: Bottom object>]
630>>> Middle.objects.all()
631[<Middle: Middle object>, <Bottom: Bottom object>]
632>>> Bottom.objects.all()
633[<Bottom: Bottom object>]
634
635
636>>> settings.DEBUG=False
637
638"""}
639