Opened 7 years ago
Closed 6 years ago
#18360 closed Cleanup/optimization (duplicate)
Database router example improvement
Description
In your example for a database router on there is one problem:
If you have several app accessing the 'other' database and multiple routers, the syncdb will not work for any app but the first one.
Currently it is:
class MyAppRouter(object): def allow_syncdb(self, db, model): "Make sure the myapp app only appears on the 'other' db" if db == 'other': return model._meta.app_label == 'myapp' elif model._meta.app_label == 'myapp': return False return None
If the database is 'other' and the app_label is not 'myapp' the router returns False and syncdb won't work for all other routers for this db.
A better example would be:
def allow_syncdb(self, db, model): if db == 'other' and model._meta.app_label == 'myapp': return True elif model._meta.app_label == 'myapp': return False return None
Change History (6)
comment:1 Changed 7 years ago by
comment:2 Changed 7 years ago by
I'm not sure I understand your report here.
The example is a specific demonstration of what you would do if "you want myapp to exist on the other database, and you want all other models in a master/slave relationship between the databases master, slave1 and slave2"; This is exactly what the provided router implements. MyAppRouter.allow_syncdb returns:
- True if you're synchronising the other database, and it is asked about a model from myapp
- False if you're synchronising the other database, and it is asked about a model that *isn't* from myapp
- False if you're synchronizing a database that isn't 'other', and it is asked about a model from myapp
- Don't care otherwise.
Your code starts to introduce "myotherapp" -- i.e., an app that isn't "myapp" -- which, by the original problem definition, should *not* be synchronised onto 'other'. That doesn't mean that myotherapp can't *access* other -- just that the models from myotherapp won't be synchronised onto other. myotherapp can still access myapp.MyModel without any problem.
You said: "If you have several app accessing the 'other' database". This is in direct conflict with the stated problem that MyAppRouter is trying to solve.
You then clarified with "there can only be one router per db". I have no idea why you are making this assertion -- the example in the docs clearly uses 2 routers, and works fine AFAICT.
Marking invalid; if I've misunderstood your report, feel free to reopen with more details. However, keep in mind that all we're trying to do here is provide an indicative problem, not provide a solution to every problem.
comment:3 Changed 7 years ago by
Hi Russel
I agree, my example was unclear and my usecase maybe too specific. Although having several apps that all need access to the 'other' database should not be too uncommon.
Anyway, this does not change the fact that I think the multi-db docs is not deep enough for developers to fully understand the concept of database routers. Here that particular example is the only example on how to use routers.
Let me explain: What guided me in the wrong direction was the naming of your example router class. Because it is named MyAppRouter it implied to me that you are going to need a router for every app. Which turned out to be wrong. Because if you do that, you won't get syncdb or dumpdata for every app that is not in the first router in the list. So if it would have been named 'OtherDbRouter' I would have instinctively used only one router for all apps that use the 'other' db, which turned out to be the correct solution.
comment:4 Changed 7 years ago by
I agree that the class name is misleading.
Scratch that example. This would cause all models to sync on the 'other' db as well.
So there can only be one router per db then (should be noted in the docs):