你说得对,跨数据库的外键是 Django ORM 中的一个问题,在某种程度上也是 db 级别的问题。
您基本上已经有了答案:“我在 Document 模型/类中可视化了一个能够检索匹配数据的函数”
我会这样做:
class RemoteObject(object):
def __init__(self, remote_model, remote_db, field_name):
# assumes remote db is defined in Django settings and has an
# associated Django model definition:
self.remote_model = remote_model
self.remote_db = remote_db
# name of id field on model (real db field):
self.field_name = field_name
# we will cache the retrieved remote model on the instance
# the same way that Django does with foreign key fields:
self.cache_name = '_{}_cache'.format(field_name)
def __get__(self, instance, cls):
try:
rel_obj = getattr(instance, self.cache_name)
except AttributeError:
system_id = getattr(instance, self.field_name)
remote_qs = self.remote_model.objects.using(self.remote_db)
try:
rel_obj = remote_qs.get(id=system_id)
except self.remote_model.DoesNotExist:
rel_obj = None
setattr(instance, self.cache_name, rel_obj)
if rel_obj is None:
raise self.related.model.DoesNotExist
else:
return rel_obj
def __set__(self, instance, value):
setattr(instance, self.field_name, value.id)
setattr(instance, self.cache_name, value)
class Document(models.Model:
name = models.CharField(max_length=200)
system_id = models.IntegerField()
system = RemoteObject(System, 'system_db_name', 'system_id')
您可能认识到上面的 RemoteObject 类实现了 Python 的描述符协议,请参阅此处了解更多信息:
https://docs.python.org/2/howto/descriptor.html
示例用法:
>>> doc = Document.objects.get(pk=1)
>>> print doc.system_id
3
>>> print doc.system.id
3
>>> print doc.system.name
'my system'
>>> other_system = System.objects.using('system_db_name').get(pk=5)
>>> doc.system = other_system
>>> print doc.system_id
5
更进一步,您可以编写自定义数据库路由器:
https://docs.djangoproject.com/en/dev/topics/db/multi-db/#using-routers
这将使您消除代码中的using('system_db_name') 调用,方法是将System 模型的所有读取路由到适当的数据库。