例如假设我有100个使用WordPress的客户端,我必须在Django中编写一个服务,该服务应该从WordPress的MySQL DB中返回 posts 的列表。问题是100个客户端具有不同的数据库连接设置。
我知道我可以使用DatabaseRouter
来切换已在设置中加载的数据库。但我不知道如何使单一模型类使用不同的数据库设置。
app_label
。但我后来才明白,在Django中改变任何东西都意味着更少。
我想创建一个模型并动态更改数据库连接。连接列表可以在managed
数据库表中。但我不想不必要地加载所有连接设置或创建多个模型。
答案 0 :(得分:2)
我做了类似的事情,但改变了mongodb连接。 我创建了一个GenericView,它选择连接并在get_queryset上使用它。
我使用django rest框架,所以我做了这样的事情:
class SwitchDBMixinView(object):
model = None
fields = None
def initial(self, request, *args, **kwargs):
result = super().initial(request, *args, **kwargs)
if request.user.is_authenticated():
request.user.database_connection.register()
return result
def get_object(self, *args, **kwargs):
return super().get_object(*args, **kwargs).switch_db(self.get_db_alias())
def get_db_alias(self):
if self.request is None or not self.request.user.is_authenticated():
return DEFAULT_CONNECTION_NAME
return self.request.user.database_connection.name
def get_queryset(self):
return self.model.objects.using(self.get_db_alias()).all()
def perform_destroy(self, instance):
instance.switch_db(self.get_db_alias()).delete()
模特:
from mongoengine.connection import register_connection, get_connection
AUTH_USER_MODEL = getattr(settings, 'AUTH_USER_MODEL')
class Connection(models.Model):
class Meta:
pass
owner = models.OneToOneField(
AUTH_USER_MODEL,
related_name='database_connection',
)
uri = models.TextField(
default=DefaultMongoURI()
)
def register(self):
register_connection(
self.name,
host=self.uri,
tz_aware=True,
)
get_connection(
self.name,
reconnect=True
)
def get_name(self):
return 'client-%d' % self.owner.pk
name = property(get_name)
def __str__(self):
return self.uri
答案 1 :(得分:1)
您可能需要查看django.db.connections
(django/db/__init__.py
)和django.db.utils.ConnectionHandler
(django.db.connections
是其中的一个实例)。这应该允许您动态添加新的数据库配置而不进行黑客攻击settings.DATABASES
(实际ConnectionHandler
从_databases
构建它的settings.DATABASES
属性。我无法确定,因为我从未尝试过,但它应该归结为
from django import db
def add_db(alias, connection_infos):
databases = db.connections.databases
if alias in databases:
either_raise_or_log_and_ignore(your choice)
db.connections.databases[alias] = connection_infos
其中connection_infos
是一个类似于settings.DATABASES
中预期的映射。
然后,主要是使用Queryset.using(alias)
进行查询,即:
alias = get_alias_for_user(request.user)
posts = Post.objects.using(alias).all()
cf https://docs.djangoproject.com/en/1.11/topics/db/multi-db/#manually-selecting-a-database
这个恕我直言的主要问题(假设您设法制作出符合上述未经测试的建议的内容)是您必须将数据库用户/密码存储在某个地方,这可能是一个重大安全问题。我不知道你对数据库管理部分有多少控制权,但如果你能在所有这些数据库上添加一个具有相同密码(当然还有适当的权限)的'django'用户会更好,这样你就可以保留密码在您的设置文件中,而不是必须将其保留在主数据库中。