#30690 closed Uncategorized (duplicate)
get_or_create() ignores database router's db_for_read() method
| Reported by: | Maciej Olko | Owned by: | nobody |
|---|---|---|---|
| Component: | Database layer (models, ORM) | Version: | 2.2 |
| Severity: | Normal | Keywords: | router, database-router, get_or_create |
| Cc: | Triage Stage: | Unreviewed | |
| Has patch: | no | Needs documentation: | no |
| Needs tests: | no | Patch needs improvement: | no |
| Easy pickings: | no | UI/UX: | no |
Description
class Foo(models.Model): # model in `legacy` app
bar = models.CharField()
class FizRouter:
@staticmethod
def db_for_read(model, **hints):
if model._meta.app_label == 'legacy':
return 'legacy'
return 'default'
@staticmethod
def db_for_write(model, **hints):
return 'default'
# file: settings.py
DATABASE_ROUTERS = ['path.FizRouter']
Foo.objects.get_or_create() will hit default database no matter if requested object is in legacy database.
I would assume that we would try to get object from legacy database and create in default if not found.
As far as I'm concerned current behaviour is not documented, IMHO it should be, if current behaviour is desired.
Note:
See TracTickets
for help on using tickets.
By it's nature of dealing with both read and writes the
get_or_createmethod has to be targeting the write database for reads.There's a comment in the method definition about it and following the
git blametrace leads to this commit.Closing as duplicate of #16865.