小编典典

Django多租户

python

Tl;
dr:有没有方法可以覆盖默认行为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标签我已经能够覆盖更换/x/正确的公司名称,我想知道是否有类似的事情,我可以做重写reverse以同样的方式,或其他任何东西,我可以做些什么来解决这个问题呢?

以前我在用

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

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

def view(request, company_name):
    ...

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


阅读 211

收藏
2020-12-20

共1个答案

小编典典

为了易于使用,Django编译了一个页面,其中包含可以完成此操作的每个可能的现有django软件包。但是下面是我自己的简单实现


我修改了我的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
)
2020-12-20