Tl; dr: Is there a way to override the default behaviour of reverse?

In my django project I have alot of urls such as

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

Which allows for urls such as

.../companyA/company/
.../companyB/company/

So that I can then use a custom middleware to modify the request to include some specific details based upon what company is using my site

This all works fine except for when django is trying to decipher the full path with reverse and {% url .. %}...

It seems to be returning /x/company/ as a default match for the regex. since the django.utils.regex_helper method next_char has an escape mapping for \w to map to x

The url tag I have been able to override to replace the /x/ with the correct company name and I am wondering if there is a similar thing I can do to override reverse in the same way, or anything else that I can do to resolve this problem?

Previously, I was using

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

But this meant I had to include a parameter in every view

def view(request, company_name):
    ...

As well as include it in all my other calls to the view (i.e with the {% url %}) which I am trying to avoid.


For ease of use, Django packages as compiled a page full of every possible existing django package that can accomplish this. However below is my own simple implementation


I modified my nginx proxy config to use the following

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

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

What this does is create a variable inside a request header that can then be used within Django. This variable I then used within a custom middleware to extend a request with a reference to the model which allows its use anywhere.

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

Examples:

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

To use this within a template, context processors must be added to the 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
)