The 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 shell 并测试一些请求,以查看向您的路由器提供的数据:
$ ./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
当尚无可用实例(在内存中)时,该值始终为空。因此,如果您需要查询参数(例如对象的 id)来确定要查询的数据库,则不能使用路由器。如果 Django 在未来提供查询或查询集对象,也许是有可能的。hints
dict.
因此,为了回答您的问题,我想说,现在您必须按照 Aaron Merriam 的建议创建一个自定义管理器。但重写只是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()
Cheers