Opened 13 years ago

Closed 10 years ago

#1667 closed defect (fixed)

OneToOne and ForeignKey related objects are cached differently

Reported by: Maniac <Maniac@…> Owned by: nobody
Component: Database layer (models, ORM) Version: master
Severity: normal Keywords: 121-rewrite
Cc: Triage Stage: Design decision needed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no


Looks like ForeignKeys respect model's custom default manager and OneToOneField don't. Here's an example.

There are 3 models: Author, Article and Contact. Article refers to Author with ForeignKey and Contact refers to Author with OneToOneField. Author has a custom default manager that gives out only authors with their 'available' field set to True:

class AvailableAuthorManager(models.Manager):
  def get_query_set(self):
    return super(AvailableAuthorManager, self).get_query_set().filter(available__exact=True)

class Author(models.Model):
  name = models.CharField(maxlength=50)
  available = models.BooleanField(default=True)
  objects = AvailableAuthorManager()
class Article(models.Model):
  author = models.ForeignKey(Author)
  title = models.CharField(maxlength=50)
class Contact(models.Model):
  author = models.OneToOneField(Author)
  address = models.CharField(maxlength=50)

Then if you have an author with available=False and an article and a contact reefering to it you get:

  • -- raises an exception DoesNotExist
  • -- returns the author

Looks like this should behave the same way in both cases. However I'm not sure how exactly but I tend to think that it should raise an exception because managers are supposed to be the ultimate mechanism to access model objects.

Change History (11)

comment:1 Changed 13 years ago by James Bennett

Using the models and manager outlined here, I created one Author, and an Article and a Contact related to it. Then I set the Author's 'available' field to False and got a DoesNotExist exception for both '' and ''. Maybe we're on different revisions and something changed between them?

comment:2 Changed 13 years ago by Maniac <Maniac@…>

Summary: OneToOne and ForeignKey treat managers differentlyOneToOne and ForeignKey related objects are cached differently

I tested it further and it seems you're right. The behavior that I was observing was caused by caching objects:

author = Author(name='...')
article = Article(author=author, title='...')
contact = Contact(author=author, address='...')  # OK  # OK

author.available=False  # Exception  # OK

So it seems that accessing object through OneToOne does use cached object and ForeignKey does a query. I'm changing summary appropriately. Now I think cached version should be used in both cases because caches are usually expected to be out of sync with reality.

comment:3 Changed 13 years ago by Maniac <Maniac@…>

Here's more. If you get a contact or an article with select_related() you will always have their authors. I mean selected_related() seems to not use managers at all.

I sorts understand why is this happening but I'm not very familiar with this code. May be I should file another bug for this?

comment:4 Changed 13 years ago by Link

Type: defect

comment:5 Changed 13 years ago by anonymous

Type: defect

comment:6 Changed 13 years ago by hi-world cup

Cc: hi-world cup added; Maniac@… removed
Keywords: rthml tab space editor js added
Summary: OneToOne and ForeignKey related objects are cached differentlyhi-world cup

comment:7 Changed 13 years ago by Adrian Holovaty

Summary: hi-world cupOneToOne and ForeignKey related objects are cached differently

comment:8 Changed 12 years ago by Gary Wilson <gary.wilson@…>

Cc: hi-world cup removed
Keywords: rthml tab space editor js removed
Triage Stage: UnreviewedDesign decision needed

comment:9 Changed 12 years ago by Adrian Holovaty

Version: magic-removalSVN

comment:10 Changed 12 years ago by Jacob

Keywords: 121-rewrite added

comment:11 Changed 10 years ago by Ivan Sagalaev

Resolution: fixed
Status: newclosed

This is actually long fixed. ForeignKey's and OneToOne behave now consistently (though they do omit default manager on purpose).

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