Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How Do I Capture the Subdomain in a Django URL Pattern?

I have a Django app that currently supports multiple languages. I'd like to add subdomain support so that going to 'de.mysite.com' queries articles in German, while 'mysite.com' queries things in English (the default language). There will be about 20 subdomains all pointing to the same Django app.

I have an abstract model with all of the fields for my data and a derived model for each language. Each language has its own database table, like so:

class ArticleBase(models.Model):
    title = models.CharField(max_length=240, unique=True)
    date_added = models.DateField(auto_now_add=True)

    class Meta:
        abstract = True

# This is English, the default.
class Article(ArticleBase):
    pass

class Article_de(ArticleBase):
    pass

I can get articles like this (I have this working today):

def article(request, title, language=None):
    if language:
        mod = get_model('app', 'Article_' + language)
        items = mod.filter(title=title)
    else:
        items = Article.objects.filter(title=title)

This is my current URL pattern:

url(r'^article/(?P<title>[a-zA-Z_-]+)/$", 'app.views.article', name='article'),

How can I parse the subdomain prefix in a URL pattern so it can be passed into the article view? Or should I be getting this info from the request when I'm processing the view?

like image 648
Jason Champion Avatar asked Oct 15 '13 15:10

Jason Champion


People also ask

How can we do URL mapping in Django?

Now, start the server and enter localhost:8000/hello to the browser. This URL will be mapped into the list of URLs and then call the corresponding function from the views file. In this example, hello will be mapped and call hello function from the views file. It is called URL mapping.

How do I reference a URL in Django?

Django offers a way to name urls so it's easy to reference them in view methods and templates. The most basic technique to name Django urls is to add the name attribute to url definitions in urls.py .

Where is URLconf in Django?

A request comes in to /hello/ . Django determines the root URLconf by looking at the ROOT_URLCONF setting. Django looks at all of the URLpatterns in the URLconf for the first one that matches /hello/ . If it finds a match, it calls the associated view function.


1 Answers

The URLS in django don't have access to the domain section of the URL, so that is not an option. Doing it manually in each view is doable but not so easy to maintain.

I think that a custom middleware solution is probably better where you check the request headers in the middleware and then load the appropriate language (or you replace the accept-language headers and let django do it's magic)

The localemiddleware can make the language available which you can then easily use to pass through to the models/queries as needed.

Also if I may ask: why store every entry in a separate table/model? Can't you just add a language field to the model and store everything in one table? Because going for 20 or so models for articles can become harder to maintain than just 1 model.

UPDATE:

I've played around a little bit and the middleware required is quite simple (although my testing was quite limited):

class SubDomainLanguage(object):
    def process_request(self, request):
        try:
            request.session['django_language'] = request.META['HTTP_HOST'].split('.')[0]
        except KeyError:
            pass

is the middleware and then change the settings to include the following:

MIDDLEWARE_CLASSES = (
    ...
    'django.contrib.sessions.middleware.SessionMiddleware',
    'subdomainmiddleware.SubDomainLanguage',
    'django.middleware.locale.LocaleMiddleware',
    ...
)

This way you can then leverage the normal Django builtin i18n support.

In the views the language is then available in request.LANGUAGE_CODE

like image 88
EWit Avatar answered Nov 04 '22 11:11

EWit