Django 多租户

Posted

技术标签:

【中文标题】Django 多租户【英文标题】:Django multi tenancy 【发布时间】:2015-07-08 10:05:32 【问题描述】:

Tl;博士:有没有办法覆盖reverse 的默认行为?

在我的 django 项目中,我有很多网址,例如

 url(r'^\w+/company/', include("company.urls", namespace="company")),

允许使用诸如

之类的网址
.../companyA/company/
.../companyB/company/

这样我就可以使用自定义中间件来修改请求,以根据正在使用我的网站的公司包含一些具体细节

除了 django 试图用 reverse% url .. % 破译完整路径时,这一切都很好......

它似乎返回/x/company/ 作为正则表达式的默认匹配项。因为django.utils.regex_helper 方法next_char 有一个转义映射\w 映射到x

url 标签我已经能够override 用正确的公司名称替换​​/x/,我想知道是否有类似的事情可以用同样的方式覆盖reverse,或者我能做些什么来解决这个问题?

以前我用的是

url(r'^(?P<company_name>\w+)/company/', include("company.urls", namespace="company"))

但这意味着我必须在每个视图中包含一个参数

def view(request, company_name):
    ...

以及将它包含在我试图避免的所有其他视图调用中(即使用% url %)。

【问题讨论】:

您正在尝试进行多租户。有几种方法可以解决这个问题(重写 reverse 不是其中之一)。见this。 @BurhanKhalid - 我查看了该链接中建议的软件包之一,他们确实做到了override reverse 尽管他们这样做的方法涉及根据设置返回不同的 url,但我希望得到一些东西更有活力(老实说,我认为这是不可能的) 【参考方案1】:

为了方便使用,Django 打包成一个page full of every possible existing django package 可以完成这个任务。不过下面是我自己的简单实现


我修改了我的 nginx 代理配置以使用以下内容

server_name ~(?<short_url>\w+)\.domainurl\.com$;

... stuff related to static files here
location / 
        proxy_set_header X-CustomUrl $short_url;
        .... other proxy settings

这样做是在请求标头中创建一个变量,然后可以在 Django 中使用该变量。然后我在自定义中间件中使用这个变量来扩展请求,并引用模型,允许在任何地方使用。

class CompanyMiddleware(object):    
    def process_request(self, request):
        if settings.DEBUG:
            request.company = CompanyClass.objects.get(id=1)
            return None

        short_url = request.META.get("HTTP_X_CUSTOMURL")

        try:
            company = CompanyClass.objects.get(short_url=short_url)
        except Model.DoesNotExist:
            return HttpResponseBadRequest('Company not found')

        request.company = company

        return None

例子:

www.companya.domainurl.com   # short_url is companya
test.domainurl.com           # short_url is test

要在模板中使用它,必须将上下文处理器添加到 settings.py

TEMPLATE_CONTEXT_PROCESSORS = (
    "django.contrib.auth.context_processors.auth",
    "django.core.context_processors.debug",
    "django.core.context_processors.i18n",
    "django.core.context_processors.media",
    'django.core.context_processors.request'  # This one in particular
)

【讨论】:

以上是关于Django 多租户的主要内容,如果未能解决你的问题,请参考以下文章

多租户 Django 应用程序:根据请求更改数据库连接?

如何将多租户 django 应用程序部署到 AWS?

多租户模式:使用 django rest 框架的动态 api 路由

添加负载均衡器时 Django 多租户站点的重定向循环

Python / Django 多租户解决方案

1.5 多租户