Opened 9 years ago

Closed 7 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: UI/UX:

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 Changed 9 years ago by ubernostrum

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 Changed 9 years ago by Maniac <Maniac@…>

  • Summary changed from OneToOne and ForeignKey treat managers differently to OneToOne 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 Changed 9 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 9 years ago by Link

  • Type defect deleted

comment:5 Changed 9 years ago by anonymous

  • Type set to defect

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

  • Cc hi-world cup added; Maniac@… removed
  • Keywords rthml tab space editor js added
  • Summary changed from OneToOne and ForeignKey related objects are cached differently to hi-world cup

comment:7 Changed 9 years ago by adrian

  • Summary changed from hi-world cup to OneToOne and ForeignKey related objects are cached differently

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

  • Cc hi-world cup removed
  • Keywords rthml tab space editor js removed
  • Triage Stage changed from Unreviewed to Design decision needed

comment:9 Changed 8 years ago by adrian

  • Version changed from magic-removal to SVN

comment:10 Changed 8 years ago by jacob

  • Keywords 121-rewrite added

comment:11 Changed 7 years ago by isagalaev

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

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