Skip to main content
 首页 » 编程设计

python之Django 中的单模型动态数据库设置

2024年08月19日29powertoolsteam

例如,假设我有 100 个使用 WordPress 的客户,我必须在 Django 中编写一个服务,它应该从 WordPress 的 MySQL DB 返回帖子列表。问题是 100 个客户端具有不同的数据库连接设置。

我知道我可以使用DatabaseRouter 来切换已经在设置中加载的数据库。但是我不知道如何制作一个单一模型类来使用不同的数据库设置。

  • 我试过改变设置。
  • 我还尝试改变模型的 app_label。

但后来我明白了,在 Django 中改变 anyting 意义不大。

我的要求

我想创建一个模型并动态更改数据库连接。连接列表可以在 managed 数据库表中。但我不想不必要地加载所有连接设置或创建多个模型。

请您参考如下方法:

我做了类似的东西,但要更改 mongodb 连接。 我创建了一个选择连接并在 get_queryset 上使用它的 GenericView。

我正在使用 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