Opened 19 years ago
Closed 16 years ago
#1667 closed defect (fixed)
OneToOne and ForeignKey related objects are cached differently
Reported by: | 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 , 19 years ago
comment:2 by , 19 years ago
Summary: | OneToOne and ForeignKey treat managers differently → 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 by , 19 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 , 18 years ago
Type: | defect |
---|
comment:5 by , 18 years ago
Type: | → defect |
---|
comment:6 by , 18 years ago
Cc: | added; removed |
---|---|
Keywords: | rthml tab space editor js added |
Summary: | OneToOne and ForeignKey related objects are cached differently → hi-world cup |
comment:7 by , 18 years ago
Summary: | hi-world cup → OneToOne and ForeignKey related objects are cached differently |
---|
comment:8 by , 18 years ago
Cc: | removed |
---|---|
Keywords: | rthml tab space editor js removed |
Triage Stage: | Unreviewed → Design decision needed |
comment:9 by , 17 years ago
Version: | magic-removal → SVN |
---|
comment:10 by , 17 years ago
Keywords: | 121-rewrite added |
---|
comment:11 by , 16 years ago
Resolution: | → fixed |
---|---|
Status: | new → closed |
This is actually long fixed. ForeignKey's and OneToOne behave now consistently (though they do omit default manager on purpose).
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?