Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/django/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
基于当前登录用户的Django数据库路由_Django_Python 3.x_Django Rest Framework - Fatal编程技术网

基于当前登录用户的Django数据库路由

基于当前登录用户的Django数据库路由,django,python-3.x,django-rest-framework,Django,Python 3.x,Django Rest Framework,在视图类中,您可以调用self.request.user并基于此执行操作。在我的情况下,我希望能够根据当前登录的用户切换数据库。是否仍然可以将self.request调用注入到db\u for_read()和db\u for_write()方法中,如下所示 class DataBaseRouter(object): def db_for_read(self, model, **hints): user = self.request.user if use

视图
类中,您可以调用
self.request.user
并基于此执行操作。在我的情况下,我希望能够根据当前登录的用户切换数据库。是否仍然可以将
self.request
调用注入到
db\u for_read()
db\u for_write()
方法中,如下所示

class DataBaseRouter(object):

    def db_for_read(self, model, **hints):
        user = self.request.user
        if user.id == 1:
            return "master"
        return "default"

    def db_for_write(self, model, **hints):
        user = self.request.user
        if user.id == 1:
            return "master"
        return "default"

您可以使用
routermiddlewar
检查用户是否登录,然后将所有
查询
重定向到您选择的特定数据库,如果您使用
基于视图的
执行查询,这将非常有帮助

class RouterMiddleware (object):

    def process_view( self, request, view_func, args, kwargs ):
        # Check the user logged in
        user = self.request.user
        # Call your functions to set the database by passing the user.id



    def process_response( self, request, response ):
        # Make the database to default here if you wish to use it no longer

        return response


class DataBaseRouter(object):

    def db_for_read(self, model, user_id=None, **hints):
       if user.id == 1:
            return "master"
        return "default"

    def db_for_write(self, model, user_id=None, **hints):
        if user.id == 1:
            return "master"
        return "default"
这是我根据您的要求修改的

请确保将
RouterMiddleware
添加到
中间件类中

尝试此操作。这很简单。安装它,并按如下方式配置和使用

设置.py

DATABASES = {
'default': {
    'ENGINE': 'django.db.backends.postgresql_psycopg2',
    'NAME': 'my_local_database',
    'USER': 'postgres',
    'PASSWORD': 'my-pass',
    'HOST': '127.0.0.1',
    'PORT': '5432',
},
'master': {
    'ENGINE': 'django.db.backends.postgresql_psycopg2',
    'NAME': 'my_master_database',
    'USER': 'postgres',
    'PASSWORD': 'my-pass',
    'HOST': 'example.com',
    'PORT': '5432',
},
}
DATABASE_ROUTERS = ['dynamic_db_router.DynamicDbRouter']
from dynamic_db_router import in_database

from my_app.models import MyModel

def index(request):
     #Picking the DB based on logged in user or you can do this in middile ware as well.
     use_db = "default"
     user = self.request.user
     if user.id == 1:
        use_db = "master"
     # Fetching data from selected databases. 
     with in_database(use_db):
         input = MyModel.objects.filter(field_a="okay")
         output = complex_query_function(input)
我的应用程序/视图.py

DATABASES = {
'default': {
    'ENGINE': 'django.db.backends.postgresql_psycopg2',
    'NAME': 'my_local_database',
    'USER': 'postgres',
    'PASSWORD': 'my-pass',
    'HOST': '127.0.0.1',
    'PORT': '5432',
},
'master': {
    'ENGINE': 'django.db.backends.postgresql_psycopg2',
    'NAME': 'my_master_database',
    'USER': 'postgres',
    'PASSWORD': 'my-pass',
    'HOST': 'example.com',
    'PORT': '5432',
},
}
DATABASE_ROUTERS = ['dynamic_db_router.DynamicDbRouter']
from dynamic_db_router import in_database

from my_app.models import MyModel

def index(request):
     #Picking the DB based on logged in user or you can do this in middile ware as well.
     use_db = "default"
     user = self.request.user
     if user.id == 1:
        use_db = "master"
     # Fetching data from selected databases. 
     with in_database(use_db):
         input = MyModel.objects.filter(field_a="okay")
         output = complex_query_function(input)

为了解决这个问题,我创建了一个新模型,其中只有一个
userid
字段。然后在路由器中,当为读写指定db时,我从该模型中获取数据,因此不需要任何请求参数。

我只是在我的基本模板中添加了一个简短的ajax代码,这样每当我的网站被打开时,它都会从request.user中获取用户id,并更改模型行,这样当前的用户id就会像这样更改。

@kartheek的答案将是一个更简单的解决方案,如果您能够灵活地在项目中安装该包的话。如果您不想检查和更改每个视图函数的数据库,可以使用中间件处理器。嘿,谢谢您的回答@kt14!我最终同意了你的答案,因为我发现它比kartheek的更容易实现。不过我确实有一个担心。有没有可能是多个请求在几乎相同的时间调用,把事情搞砸了?例如,Request1>user.id=1 Request2>user.id=2 Response1>获取user.id=2导致错误我认为这不应该是任何问题,因为django将为用户传递的每个请求创建一个新的请求对象,无论两个不同的用户同时查询,查询将通过上下文处理器,并且将选择特定的数据库,因此就我所知不会有交叉交互。@kt14嗨,我真的不明白我们如何将user.id注入router类。在链接的代码段中,我们使用threading.local()来共享这个,但我无法使它在django 2.1.4上工作。可能对此有一些更改?好的,很抱歉,这是因为使用了Django版本的中间件。添加了init和call,现在一切都好了。嘿@Kartheek,谢谢你的回答!虽然我很感激,但我最终还是选择了kt14,因为我发现他的答案更容易实现,因为我的项目涉及近百个视图,因此为每个视图编写代码是不可行的。谢谢你抽出时间@Lorenzo我提到了内联注释,您可以将该逻辑转移到中间件。这是另一种实施方式。不管怎样,我很高兴你找到了解决办法。