Provide object's primary key as a hint for database router method db_for_read() when filtering objects by primary key
|Reported by:||Owned by:||nobody|
|Component:||Database layer (models, ORM)||Version:||1.2|
|Cc:||noah@…||Triage Stage:||Design decision needed|
|Has patch:||no||Needs documentation:||no|
|Needs tests:||no||Patch needs improvement:||no|
Setting up a custom database router with db_for_read() method to allow for sharding with MySQL. Need to be able to control what database an object is read from on a per-object basis.
I want to retrieve User objects from the database cluster as follows:
- If the username starts with a number, read from slave_db_1
- If the username starts with a letter, read from slave_db_2
Currently, the only way to achieve this behavior is to specify "using" on each condition, and per each call to the database.
When filtering objects by primary key, pass the primary key to db_for_read() as a hint.
#View Code: """Assume username is pk for User model""" users = User.objects.get(username="testuser") #DB Router Code class UserReadRouter(object): def db_for_write(self, model, **hints): return 'master' def db_for_read(self, model, **hints): """Assume pk of User object is a string""" if model.__name__ == "User" and 'object_pk' in hints: if hints['object_pk'].isalpha(): return 'slave_db_2' else: return 'slave_db_1'
The end result is that "testuser" is retrieved from slave_db_1.