我假设您已经扩展了您的系统,并且目前您正在使用负载平衡器从两台机器上为您的网站提供服务。您想知道,在不使用粘性会话的情况下,我们如何为会话维护服务器和客户端之间的连接。
同样在您所说的评论中,您可能拥有多个数据库,这些数据库可以提供不同的服务,也可以托管在某个远程位置。此外,由于您已指定您的数据库之一将处理与用户相关的内容和其他与网站相关的内容。
首先,我想给你一个关于如何实现这一点的工作流程:
- 在您的 setting.py 文件中指定多个数据库。
- 每个任务都有一个集中的数据库
- 使用 using 参数指定您在保存任何数据时引用的数据库之一(如果未指定路由器)。
- 最好使用路由器而不是每次都手动指定数据库。
- 请记住,用户身份验证和会话,您不必将其显式存储在数据库中,一旦您在 setting.py 文件中指定它,django 就会处理它。因为您的所有服务器机器都将连接到同一个数据库以进行身份验证和其他东西。
- 您的所有服务器都将使用相同的集中式数据库来存储客户端和服务器之间的 HTTP 连接的会话变量,从而维护状态。
因此,这是您如何实现相同目标的简要概述。现在让我们在代码中看到这一点。
在 setting.py 文件中指定多个数据库
指定要在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 和 contenttypes 应用程序的查询发送到 auth_db 的路由器
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,允许您在代码中保持对数据库使用的完全控制。手动指定的数据库分配将优先于路由器分配的数据库。请参阅文档。