Django多租户:如何为每个租户自定义Django设置中的“ACCOUNT_EMAIL_VERIFICATION”?

3
Django==1.11.7
django-tenant-schemas==1.8.0
django-allauth==0.34.0

使用django-tenant-schemas (postgres)创建多租户网站。 在不同的租户中,需要不同的设置。
更具体地说,ACCOUNT_EMAIL_VERIFICATION需要不同的设置。
一个租户需要 `ACCOUNT_EMAIL_VERIFICATION = "optional"`,而另一个租户需要 `ACCOUNT_EMAIL_VERIFICATION ="mandatory"`。
查看源代码,发现该设置似乎无法自定义,它是针对整个django站点固定的。
-> 如何实现这一点?
3个回答

4
你可以在运行时计算设置,因为它只是Python代码。
使用你喜欢的方式以编程方式设置特定的代码。一个例子:
# predefine the settings per tenant
ACCOUNT_EMAIL_VERIFICATION_PER_TENANT = {
    "tenant_x": "mandatory",
    "tenant_y": "optional",
}

# implement get_tenant 

def get_tenant():
    # here be tenant logic
    pass

this_tenant = get_tenant()
ACCOUNT_EMAIL_VERIFICATION = ACCOUNT_EMAIL_VERIFICATION_PER_TENANT[get_tenant()]

或者您可以拥有多个设置文件并根据需要加入它们。这里是Django如何处理

哦,如果您想将逻辑与设置文件分开,并在评估设置之前运行它,您可以检查启动服务器时的执行轨迹(例如从manage.py开始),并在其中某个位置插入您的get_tenant逻辑。很可能会从wsgi.py文件开始 - 在那里创建了application实例并开始所有Django乐趣的地方。

在编程方面,您始终处于控制之中。


有趣的方法。在测试时,我遇到了问题,因为 get_tenant 逻辑包括 return connection.schema_name,需要在 SETTINGS 文件顶部加上 from django.db import connection。显然,这会导致设置文件出现问题,因为我的 SECRET KEY 不再被找到,虽然它明显存在且未更改,结果导致 django.core.exceptions.ImproperlyConfigured: The SECRET_KEY setting must not be empty - Davy
跟进问题:为什么需要这行代码 this_tenant = get_tenant() - Davy
尝试使用 ACCOUNT_EMAIL_VERIFICATION = lambda: get_tenant_email_verification(),其中 get_tenant_email_verification() 函数立即返回 mandatoryoptional。然后,lambda 避免了在读取设置时出现的错误,但由于某种原因,在使用变量时 lambda 没有被评估。 - Davy
当变量被使用时,lambda表达式不会被评估,实际上是在服务器启动时进行评估的。这就是所有设置都被评估的时候。您需要跟踪执行的内容以及何时执行,并在正确的时间插入“get_tenant”逻辑。例如,如果您使用“manage.py”,则可以从那里开始并找出上下文中的正确位置。或者,您可以使用“wsgi.py”文件来处理您的服务器。然后从那里开始。 - Adelin
Lambda方法确实无法工作。 wsgi.py如何有任何用处并不清楚。现在相当空:'from django.core.wsgi import get_wsgi_application' 'application = get_wsgi_application()' - Davy

3

我遇到了这种情况,我的动态解决方案是一个中间件,没有硬编码租户的名称,如下所示。

from django.conf import settings
from django.db import connection
from django_tenants.utils import get_public_schema_name, get_tenant_model

class TenantSettingsMiddleWare:
    def __init__(self, get_response):
        self.get_response = get_response

    def __call__(self, request):
        self.request = request
        self.overload_settings()
        response = self.get_response(request)
        return response

    def overload_settings(self):
        current_schema_obj = get_tenant_model().objects.get(schema_name=connection.schema_name)
        settings.DEFAULT_FROM_EMAIL = 'admin@{}'.format(current_schema_obj.domains.last())


干杯


0
解决方法如下:
在 settings.py 文件中:
try:
    ACCOUNT_EMAIL_VERIFICATION = os.environ['ACCOUNT_EMAIL_VERIFICATION_OVERRIDE']
except KeyError:
    ACCOUNT_EMAIL_VERIFICATION = 'mandatory'

在可选电子邮件验证的租户的wsgi.py文件中:
os.environ['ACCOUNT_EMAIL_VERIFICATION_OVERRIDE'] = 'optional'

其他租户的wsgi文件保持不变。


把赏金给了Adelin,因为他建议查看wsgi文件。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接