Параметр hints
разработан, чтобы помочь вашему маршрутизатору базы данных решить, куда он должен читать или записывать свои данные. Он может развиваться с будущими версиями python, но на данный момент есть только один вид подсказки, который может дать инфраструктура Django, и это instance
, над которой он работает.
Я написал этот очень простой маршрутизатор базы данных, чтобы увидеть, что делает Django:
# routers.py
import logging
logger = logging.getLogger("my_project")
class DebugRouter(object):
"""A debugging router"""
def db_for_read(self, model, **hints):
logger.debug("db_for_read %s" % repr((model, hints)))
return None
def db_for_write(self, model, **hints):
logger.debug("db_for_write %s" % repr((model, hints)))
return None
def allow_relation(self, obj1, obj2, **hints):
logger.debug("allow_relation %s" % repr((obj1, obj2, hints)))
return None
def allow_syncdb(self, db, model):
logger.debug("allow_syncdb %s" % repr((db, model)))
return None
Вы заявляете это в settings.py
:
DATABASE_ROUTERS = ["my_project.routers.DebugRouter"]
Убедитесь, что протоколирование правильно сконфигурировано для вывода отладочной информации (например, в stderr):
LOGGING = {
'version': 1,
'disable_existing_loggers': False,
'handlers': {
[...some other handlers...]
'stderr': {
'level': 'DEBUG',
'class': 'logging.StreamHandler'
}
},
'loggers': {
[...some other loggers...]
'my_project': {
'handlers': ['stderr'],
'level': 'DEBUG',
'propagate': True,
},
}
}
Затем вы можете открыть оболочку Django и протестировать несколько запросов, чтобы увидеть, какие данные получает ваш маршрутизатор:
$ ./manage.py shell
[...]
>>> from my_project.my_app.models import User
>>> User.objects.get(pk = 1234)
db_for_read (<class 'my_project.my_app.models.User'>, {})
<User: User object>
>>> user = User.objects.create(name = "Arthur", title = "King")
db_for_write (<class 'my_project.my_app.models.User'>, {})
>>> user.name = "Kong"
>>> user.save()
db_for_write (<class 'my_project.my_app.models.User'>, {'instance':
<User: User object>})
>>>
Как видите, hints
всегда пуст, когда еще нет экземпляра (в памяти). Таким образом, вы не можете использовать маршрутизаторы, если вам нужны параметры запроса (например, идентификатор объекта), чтобы определить, какую базу данных запрашивать. Это может произойти в будущем, если Django предоставит объекты запроса или набора запросов в hints
dict.
Итак, чтобы ответить на ваш вопрос, я бы сказал, что сейчас вы должны создать собственного менеджера, как это предложил Аарон Мерриам. Но переопределения только метода create
недостаточно, поскольку вам также необходимо иметь возможность извлекать объект в соответствующей базе данных. Примерно так может работать (пока не тестировалось):
class CustomManager(models.Manager)
def self.find_database_alias(self, pk):
return #... implement the logic to determine the shard from the pk
def self.new_object_database_alias(self):
return #... database alias for a new object
def get(self, *args, **kargs):
pk = kargs.get("pk")
if pk is None:
raise Exception("Sharded table: you must provide the primary key")
db_alias = self.find_database_alias(pk)
qs = self.get_query_set().using(db_alias)
return qs.get(*args, **kargs)
def create(self, *args, **kwargs):
db_alias = self.new_object_database_alias()
qs = super(CustomManager, self).using(db_alias)
return qs.create(*args, **kwargs)
class ModelA(models.Model):
objects = CustomManager()
Приветствия