在开发索引系统文档的网站时,我遇到了一个棘手的难题,就是在Django的数据库中,数据“匹配”/relations。
本地数据库的简化模型:
from django.db import models
class Document(models.Model):
name = models.CharField(max_length=200)
system_id = models.IntegerField()
...想象中的模型,系统细节存储在一个远程数据库中。
from django.db import models
class System(models.Model):
name = models.CharField(max_length=200)
system_id = models.IntegerField()
...这个想法是,在我的网站上创建一个新的文档条目时,相关系统的ID将存储在本地数据库中。在显示数据时,我必须使用存储的ID从远程数据库检索系统名称和其他详细信息。
我已经调查过跨数据库的外键,但这似乎是非常广泛的,我不确定我是否想要关系。相反,我在文档模型/类中可视化了一个函数,它能够检索匹配的数据,例如通过导入自定义路由器/函数。
我该怎么解决这个问题?
请注意,我无法更改远程数据库上的任何内容,而且它是只读的。不确定我是否也应该为系统创建一个模型。这两个数据库都使用PostgreSQL,但是我的印象是,它与使用数据库的这个场景并不真正相关。
发布于 2014-07-10 13:40:38
在django文档多数据库(手动选择数据库)中
# This will run on the 'default' database.
Author.objects.all()
# So will this.
Author.objects.using('default').all()
# This will run on the 'other' database.
Author.objects.using('other').all()
The 'default' and 'other' are aliases for you databases.
In your case it would could be 'default' and 'remote'.当然,您可以将.all()替换为您想要的任何东西。
Example: System.objects.using('remote').get(id=123456)发布于 2014-07-15 15:48:33
您是正确的,跨数据库的外键在Django ORM中是一个问题,在某种程度上也是db级别的问题。
您已经得到了基本的答案:“我在文档模型/类中可视化了一个函数,它能够检索匹配的数据”。
我会这样做:
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更进一步,您可以编写一个自定义db路由器:
https://docs.djangoproject.com/en/dev/topics/db/multi-db/#using-routers
这将使您能够通过将System模型的所有读取路由到适当的db来消除代码中的System调用。
发布于 2014-07-14 20:18:37
我会选择一个方法get_system()。所以:
class Document:
def get_system(self):
return System.objects.using('remote').get(system_id=self.system_id)这是最简单的解决办法。一个可能的解决方案也是使用PostgreSQL的外部数据包装功能。通过使用FDW,您可以从django抽象出多数据库处理,并在数据库中进行--现在您可以使用需要使用文档->系统关系的查询。
最后,如果您的用例允许,只需定期将系统数据复制到本地db即可是一个很好的解决方案。
https://stackoverflow.com/questions/24628777
复制相似问题