Opened 8 years ago

Closed 8 years ago

#7214 closed (duplicate)

Bug in OneToOneField cache

Reported by: m.gajda@… Owned by: nobody
Component: Core (Other) Version: master
Severity: Keywords: one to one cache bug
Cc: Triage Stage: Unreviewed
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: UI/UX:


There is a fatal bug in OneToOneField cacheing subsystem. Consider following models:

class A( models.Model ):
  foo = models.IntegerField()

  def __unicode__( self ):
    return "%d" %

class B( A ):
    a = models.OneToOneField( A , related_name = "b" , parent_link = True )

class C( A ):
    a = models.OneToOneField( A , related_name = "c" , parent_link = True )

> B(foo=1).save()

> C(foo=2).save()

> A.objects.all()
[<A: 1>, <A: 2>]

> a = A.objects.filter( foo = 1 )[0]

> a.b
<B: 1>

> a.c
<B: 1>

In both cases (b and c fields pointing to different subclasses) is returns the same object, but in the second case an exception should be throwed.

The reason is cacheing subsystem in SingleRelatedObjectDescriptor class of the module django.db.models.fields.related. In the constructor it creates twice cache with the same so called cache name: self.cache_name = '_%s_cache' % because points to the same string in both cases. In my opinion it should point to different strings. After aplying attached patch, which uses just instead of everything seems to work correctly (cache still works but separately for both fields).

> A.objects.all()
[<A: 1>, <A: 2>]

> a = A.objects.filter( foo = 1 )[0]

> a.b
<B: 1>

> a.c
<class 'megasite.test.models.DoesNotExist'>: C matching query does not exist.

Attachments (1)

a (551 bytes) - added by m.gajda@… 8 years ago.

Download all attachments as: .zip

Change History (3)

Changed 8 years ago by m.gajda@…

  • Attachment a added

comment:1 Changed 8 years ago by gav

  • Needs documentation unset
  • Needs tests unset
  • Patch needs improvement unset

I believe this is a dupe of #7173. I also believe that the patch on #7173 is a better solution, as it's using the proper function from the RelatedField, get_accessor_name(). Recommending for resolution of duplicate.

comment:2 Changed 8 years ago by ubernostrum

  • Resolution set to duplicate
  • Status changed from new to closed

Yup, it's a dupe of #7173.

Note: See TracTickets for help on using tickets.
Back to Top