【问题标题】:Django multitenant: how to customize django setting "ACCOUNT_EMAIL_VERIFICATION" per tenant?Django 多租户:如何为每个租户自定义 django 设置“ACCOUNT_EMAIL_VERIFICATION”?
【发布时间】:2022-01-28 04:10:43
【问题描述】:
Django==1.11.7
django-tenant-schemas==1.8.0
django-allauth==0.34.0

使用 django-tenant-schemas (postgres) 的多租户站点。 在不同的租户上,需要不同的设置。

更具体地说,ACCOUNT_EMAIL_VERIFICATION 需要不同的设置

1 个租户需要 ACCOUNT_EMAIL_VERIFICATION = "optional",而另一个租户需要 ACCOUNT_EMAIL_VERIFICATION ="mandatory"

查看source code,该设置看起来不可自定义,对于整个 django 站点是固定的。

-> 如何做到这一点?

【问题讨论】:

    标签: django multi-tenant django-allauth


    【解决方案1】:

    您可以在运行时计算设置,因为它只是一个 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()]
    

    或者您可以拥有多个设置文件并根据需要加入它们。这里是how django does

    哦,如果您想将逻辑从设置文件中分离出来并在评估设置之前运行它,您可以在启动服务器时检查执行轨迹是什么(例如,从 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
    • 后续问题:为什么需要this_tenant = get_tenant()这一行?
    • 尝试使用ACCOUNT_EMAIL_VERIFICATION = lambda: get_tenant_email_verification(),其中get_tenant_email_verification() 函数立即返回mandatoryoptional。然后 lambda 会在读取设置时避免错误,但由于某种原因,在使用变量时不会评估 lambda。
    • lambda 确实在使用变量时不会被评估。它在服务器启动时进行评估。那是评估所有设置的时候。您需要跟踪何时执行的操作,并在正确的时间插入get_tenant 逻辑。例如,如果您使用manage.py,您可以从那里开始并找出在您的上下文中正确的位置。或者也许您使用wsgi.py 文件来处理您的服务器。那就从那里开始
    • lambda 方法确实行不通。不清楚 wsgi.py 对此有何用处。现在比较空:from django.core.wsgi import get_wsgi_applicationapplication = get_wsgi_application()
    【解决方案2】:

    通过以下方式解决:

    在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 文件,将赏金奖励给他。

    【讨论】:

      【解决方案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())
      
      
      

      干杯???

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2015-07-08
        • 1970-01-01
        • 2012-08-29
        相关资源
        最近更新 更多