#13432 closed (fixed)
OneToOneField between two databases fails
Reported by: | Benjamin Wohlwend | Owned by: | nobody |
---|---|---|---|
Component: | Database layer (models, ORM) | Version: | dev |
Severity: | Keywords: | multidb | |
Cc: | Triage Stage: | Accepted | |
Has patch: | yes | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
When model A is in the default database and model B is in another database, and there is a OneToOne relation between the two models, the lookup fails (raising a DoesNotExist, or if the tables aren't in both databases, a ProgrammingError). Writing works, only reading fails. I have no idea of the ORM internals, so I might be completely wrong, but I think the cause is a simple copy&paste error. Fix and test is in the patch.
Attachments (1)
Change History (4)
by , 15 years ago
Attachment: | one_to_one_multidb.diff added |
---|
comment:1 by , 15 years ago
Triage Stage: | Unreviewed → Accepted |
---|
comment:2 by , 15 years ago
Resolution: | → fixed |
---|---|
Status: | new → closed |
Note:
See TracTickets
for help on using tickets.
This is a case of being technically correct, for the wrong reason.
You are correct that self.related.model is technically the right argument to pass in. However, it doesn't make a huge difference in practice, because self.related.model and instance.class must route to compatible databases (i.e., you must be able to find objects of both types on the same database). If there is a relationship between the two objects, they must be on databases that allow joins.
In the example you give, the two models are on different databases - which would be prohibited on any database that honors referential integrity. Your example should have an "allows_join" method that prohibits cross-database joins, which would prohibit the creation of the UserProfile instance in the first place.
There are cases where you will be able to get away with the type of router you describe - if you use MySQL/MyISAM or SQLite, and you don't ever issue a
User.objects.filter(userprofile__flavor='foo')
query, for instance; but in general I would advise against this unless you have really thought through the consequences.There is an edge case where model-based load balancing behavior might cause this issue to be observed, but only in the sense that queries would be directed to the wrong slave (answers wouldn't be wrong, just served by the wrong database), so the problem is still worth solving. I'll also use this as an opportunity to add some tests for o2o relations, which weren't fully tested previously.