首页 > 解决方案 > 如何在 django 的模型管理器上动态交换默认数据库?

问题描述

我正在 django 和 django rest 框架中创建一个项目。它是一个角度应用程序的 api。数据库设置由多个数据库组成。一个是默认数据库,所有的 django 表都驻留在这个数据库中;其余的数据库属于一种用户类型,每个用户都应该有一个单独的数据库。因此,所有与用户相关的数据都进入其单独的数据库。为了动态实现选择数据库,用户对象有一个额外的字段来存储要写入的数据库。

from django.contrib.auth.models import AbstractUser

class CustomUser(AbstractUser):
    """Custom User model."""

    database= models.CharField(max_length=9)

这样做的原因是提高了性能,因为每个数据库都是独立的,ListView 和 DetailView 的工作速度会比数据仅存储在一个数据库中更快。

我知道我可以使用模型管理器上的 using 方法来选择要存储的数据库。在其余的 api 中,一切正常,数据存储在各自的数据库中,但我最终覆盖了 django 定义的方法。它增加了项目的开发成本。外键和多对多键需要用用户的当前数据库来解析,因为我已经自定义了数据库设置,所以没有发生这种情况。此外,我的代码不如他们的 :p 好,因为他们多年来一直在编写 django。

我已经覆盖了很多查询集,但是 django 仍然多次使用默认数据库。如果我只能在 django 模型的模型管理器中使用请求对象来根据每个请求交换默认数据库,我认为情况会有所不同。

我的问题是——

  1. 有没有办法在模型管理器中访问请求对象?我可以做一些事情来影响下面的代码。

    类 CustomManager(models.Manager):

    def get_queryset(self, request):
    
        return super(CustomManager, self).using(request.user.database).get_queryset()
    
  2. 模型管理器具有可用于选择数据库的 _db 属性。会建议覆盖它吗?如果是,代码中的方式和位置?

  3. 有没有更好的方法来实现单独的数据库?

提前致谢。

问候

标签: djangodjango-rest-frameworkpython-3.7

解决方案


在 Django 文档中建议使用数据库路由器,但问题是它只访问模型类。

发现了几个与动态切换数据库问题相关的问题。这篇文章有一个解决方案,可以解决使用实例request.user传递或任何其他参数的问题。threading.local

有人甚至为此创建了一个可重用的插件 - https://github.com/ambitioninc/django-dynamic-db-router

希望有帮助。


推荐阅读