如何在 Django 模型管理器上动态交换默认数据库?

How to dynamically swap default database on the model manager in django?

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

from django.contrib.auth.models import AbstractUser

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

    database= models.CharField(max_length=9)

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

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

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

我的问题是 -

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

    class 自定义管理器(models.Manager):

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

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

提前致谢。

此致

Using a database router is recommended in Django docs,但问题是它只能访问模型 class。

发现了几个与动态切换数据库相关的问题。 This post has a solution that would solve the problem of passing the request.user or any other parameter by using a threading.local instance.

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

希望对您有所帮助。