Opened 18 years ago

Closed 15 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: dev
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

Description

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:

  • article.author -- raises an exception DoesNotExist
  • contact.author -- 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 by James Bennett, 18 years ago

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 'article.author' and 'contact.author'. Maybe we're on different revisions and something changed between them?

comment:2 by Maniac <Maniac@…>, 18 years ago

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='...')
author.save()
article = Article(author=author, title='...')
article.save()
contact = Contact(author=author, address='...')
contact.save()

article.author  # OK
contact.author  # OK

author.available=False
author.save()

article.author  # Exception
contact.author  # 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 by Maniac <Maniac@…>, 18 years ago

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 by Link, 18 years ago

Type: defect

comment:5 by anonymous, 18 years ago

Type: defect

comment:6 by hi-world cup, 18 years ago

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 by Adrian Holovaty, 18 years ago

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

comment:8 by Gary Wilson <gary.wilson@…>, 17 years ago

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

comment:9 by Adrian Holovaty, 17 years ago

Version: magic-removalSVN

comment:10 by Jacob, 16 years ago

Keywords: 121-rewrite added

comment:11 by Ivan Sagalaev, 15 years ago

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