Django 多租户

Django multi tenancy

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

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

 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 %})。

为了方便使用,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
}

这样做是在请求 header 中创建一个变量,然后可以在 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
)