繁体   English   中英

如何在数据库中存储和检索 Django 会话变量?

[英]How can I store and retrieve Django session variable to/from database?

我有我的 Django 网站,该网站目前由两台机器使用负载平衡器提供服务。 我想从一台机器上维护与用户对应的会话。 我知道我可以将负载平衡器配置为使用粘性会话,这样来自用户的所有请求都将由同一台服务器提供服务。 但我想使用会话变量来实现相同的目的。

这就是我如何将该会话变量存储在集中式数据库中,任何服务器都可以从中访问该用户的会话,因此任何服务器都可以通过使用该会话变量存储来为其提供服务。 但是我无法理解流程以及如何在 Django 中实现相同的流程。

所以我的问题是如何为用户将会话保存在数据库中,以便任何服务器能够访问它并相应地为请求提供服务。 在这种情况下,这些 login() 和 logout 将如何工作?

我也有多个数据库。 我计划将一个用于用户身份验证和其他内容,另一个用于网站相关数据存储。 或者任何人至少可以向我解释如何实现这一目标的流程。

我假设您已经扩展了系统,并且目前您正在使用负载平衡器从两台机器上为您的网站提供服务。 您想知道在不使用粘性会话的情况下,我们如何为会话维护服务器和客户端之间的连接。

同样在评论中,您说您可能拥有多个数据库,这些数据库可以提供不同的服务,也可以托管在某个远程位置。 此外,由于您已指定您的数据库之一将处理与用户相关的内容和其他与网站相关的内容。

首先,我想为您提供一个有关如何实现此目标的工作流程:

  • 在 setting.py 文件中指定多个数据库。
  • 每个任务都有一个集中的数据库
  • 使用 using 参数指定在保存任何数据时所引用的数据库之一(如果未指定路由器)。
  • 最好使用 Router 而不是每次都手动指定数据库。
  • 请记住,用户身份验证和会话,您不必将其显式存储在数据库中,一旦您在 setting.py 文件中指定它,django 就会处理它。 因为您的所有服务器机器都将连接到相同的数据库以进行身份​​验证和其他内容。
  • 您的所有服务器都将使用相同的集中式数据库来存储客户端和服务器之间 HTTP 连接的会话变量,从而维护状态。

因此,这是对如何实现相同目标的简要概述。 现在让我们在代码中看到这一点。

在 setting.py 文件中指定多个数据库

DATABASES字典中指定要使用的所有DATABASES 当您没有明确指定要将数据保存到的数据库时,将使用默认值,所有其他内容将使用默认值进行读写。 如果您明确希望为每个数据库指定,那么您需要小心始终指定要用于存储/检索的数据库。

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': 'app_data',
        'USER': 'mydatabaseuser',
        'PASSWORD': 'mypassword',
        'HOST': '127.0.0.1',
        'PORT': 'XXXX',
    },
    'auth_db': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': 'auth_db',
        'USER': 'mydatabaseuser',
        'PASSWORD': 'mypassword',
        'HOST': '127.0.0.1',
        'PORT': 'XXXX',
    },
}

为用户和网站阅读的内容明确指定不同的数据库

DATABASES = {
    'default': {},
    'auth_db': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': 'auth_db',
        'USER': 'mydatabaseuser',
        'PASSWORD': 'mypassword',
        'HOST': '127.0.0.1',
        'PORT': 'XXXX',
    },
    'customers': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': 'customers',
        'USER': 'mydatabaseuser',
        'PASSWORD': 'mypassword',
        'HOST': '127.0.0.1',
        'PORT': 'XXXX',
    }
}

Django 要求定义一个默认的数据库条目,但如果不使用,参数字典可以留空。 在这种情况下,您必须明确指定在保存数据时将使用哪个数据库,或者您可以为其指定ROUTER

如果您尝试访问未在 DATABASES setting定义的数据库,Django 将引发django.db.utils.ConnectionDoesNotExist异常。

同步数据库

migrate管理命令一次对一个数据库进行操作。 默认情况下,它在default数据库上运行,但通过提供--database选项,您可以告诉它同步不同的数据库。

例子 :

$ python manage.py migrate --database=users
$ python migrate --database=customers

路由用户身份验证和来自不同数据库的网站相关数据

我们希望自动处理它,而不是每次使用using参数指定数据库的名称。 我们需要处理路由。 首先,我们需要一个知道向 auth_db 发送对 auth 和 contenttypes 应用程序的查询的路由器

class AuthRouter:
    """
    A router to control all database operations on models in the
    auth and contenttypes applications.
    """
    route_app_labels = {'auth', 'contenttypes'}

    def db_for_read(self, model, **hints):
        """
        Attempts to read auth and contenttypes models go to auth_db.
        """
        if model._meta.app_label in self.route_app_labels:
            return 'auth_db'
        return None

    def db_for_write(self, model, **hints):
        """
        Attempts to write auth and contenttypes models go to auth_db.
        """
        if model._meta.app_label in self.route_app_labels:
            return 'auth_db'
        return None

    def allow_relation(self, obj1, obj2, **hints):
        """
        Allow relations if a model in the auth or contenttypes apps is
        involved.
        """
        if (
            obj1._meta.app_label in self.route_app_labels or
            obj2._meta.app_label in self.route_app_labels
        ):
           return True
        return None

    def allow_migrate(self, db, app_label, model_name=None, **hints):
        """
        Make sure the auth and contenttypes apps only appear in the
        'auth_db' database.
        """
        if app_label in self.route_app_labels:
            return db == 'auth_db'
        return None

同样,您可以为其他数据库创建路由器。

最后,在设置文件中,我们添加以下内容(将 path.to. 替换为定义路由器的模块的实际 Python 路径):

DATABASE_ROUTERS = ['path.to.AuthRouter', 'path.to.OtherDBRouter']

处理路由器的顺序很重要。 路由器将按照它们在 DATABASE_ROUTERS 设置中列出的顺序进行查询。 在这个例子中,AuthRouter 在 OtherDBRouter 之前被处理,因此,关于 auth 中的模型的决定在做出任何其他决定之前被处理。

从/向数据库检索/存储数据。

安装此设置后,让我们运行一些 Django 代码:

>>> # This retrieval will be performed on the 'auth_db' database
>>> fred = User.objects.get(username='fred')
>>> fred.first_name = 'Frederick'

>>> # This save will also be directed to 'auth_db'
>>> fred.save()

默认路由方案确保对象保持“粘性”到其原始数据库(即,从 foo 数据库检索的对象将保存在同一数据库中)。 默认路由方案确保如果未指定数据库,则所有查询都回退到默认数据库。

创建模型

现在您一定在想,在这种情况下,我如何为不同的数据库创建模型,以便我们可以使用 Django ORM 的酷炫功能。

在这种情况下,您必须指定到数据库名称的映射。

在您的setting.py文件中添加,

DATABASE_APPS_MAPPING = {'user_data': 'auth_db',
                        'customer_data':'customers'}

相应的模型将被修改为

class User(models.Model):
    username = models.Charfield(ax_length=100)
    class Meta:
        app_label = 'user_data'

class Customer(models.Model):
    name = models.TextField(max_length=100)
    class Meta:
        app_label = 'customer_data'

有关更多信息并手动选择用于存储/检索的数据库。 Django 还提供了一个 API,允许您在代码中保持对数据库使用的完全控制。 手动指定的数据库分配将优先于路由器分配的数据库。 请参阅文档

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM