4

I am using django-registration along side django auth for my client account creation and login.

Our site will be used by moble users and desktop users. We just started tackling the idea of mobile users by loading different templates from the view depending on user agent strings. It's cleanly done, but I am not sure if it is the right way to do it as we are now stuck with what to do on views that are not easily accessible (that we didn't write ourselves).

Which brings me to the problem at hand: I have no idea how to tackle redirecting the mobile user away from the login url that django-registration/auth sends them to (the desktop version).

I could change tactics and tackle the different browsers in the template files themselves. That feels like it is going to get messy fast. I don't like that idea at all!

Or I stay with my current method, which is to render the request with different templates based on user agent strings. Then i need to know how I should be dealing with django-registration (how to load a different set of templates based on the user agent string). I would rather not change the django-registration code, if just to make updating modules easier.

michael
  • 2,577
  • 5
  • 39
  • 62

2 Answers2

2

The django registration templates are very simple and are used very rarely. I simply handle these as special cases and just come up with a base.html for that works on both platforms reasonably well.

My registration pages look very simple, many sites do this and it is not unexpected.

Another option is to us a middleware which sets the template directory based upon detecting if it is a mobile device. You can detect the mobile browser like this Detect mobile browser (not just iPhone) in python view and then have a middleware that uses the make_tls_property trick to update the TEMPLATE_DIRS something like this:

TEMPLATE_DIRS = settings.__dict__['_wrapped'].__class__.TEMPLATE_DIRS = make_tls_property(settings.TEMPLATE_DIRS)

class MobileMiddleware(object):
    """Sets settings.SITE_ID based on request's domain"""
    def process_request(self, request):
        if *mobile*:
            TEMPLATE_DIRS.value = *mobiletemplates* + settings.BASE_TEMPLATE_DIRS
        else:
            TEMPLATE_DIRS.value = *normaltemplates* + settings.BASE_TEMPLATE_DIRS

Just to be clear, make_tls_property, which is part of djangotoolbox, makes the TEMPLATE_DIRS setting a per thread variable instead of a global variable so each request response loop gets it's own "version" of the variable.

Community
  • 1
  • 1
Rob Osborne
  • 4,897
  • 4
  • 32
  • 43
  • A good answer for the near term, but the general problem will remain as at some point I may want to actually load different templates for whatever reason. – michael Aug 08 '11 at 00:14
  • Awesome, we will be using a very basic login for now (your first suggestion), but will try out your middle ware suggestion for future use if needed. – michael Aug 10 '11 at 18:04
  • The middleware solution has the problem that `TEMPLATE_DIRS` is a global attribute, so it's persisted from one request to the next. Generally it wouldn't be a problem, but if you have a high traffic site you will render a page with the wrong `TEMPLATE_DIRS` from time to time, due to timing issues on the web server's request thread. – Daniel Naab Aug 10 '11 at 22:19
  • Instead of monkey patching `settings.TEMPLATE_DIRS`, just deploy another instance of the site, with the exact same settings, but different template directories, like http://example.com and http://mobile.example.com (or even http://m.example.com to save typing). Then the middleware would just redirect to the corresponding domain based on the user agent string. – Armando Pérez Marqués Aug 10 '11 at 22:36
  • @Daniel, you're correct, the code would need to remove the mobile templates if it was for a non-mobile browser. Fixed. – Rob Osborne Aug 11 '11 at 00:33
  • @Mandx, but then you would need two sets of redundant servers, one for mobile and one for without. Great if your site is big enough to require 4+ web application servers anyway. – Rob Osborne Aug 11 '11 at 00:38
  • @Rob It still has the same problem. TEMPLATE_DIRS is a module attribute on the settings module... it's shared among the entire Django instance. If the web server has two requests coming in on different threads at the same time, the TEMPLATE_DIRS attribute isn't guaranteed to be what you intend. Better to stick with thread locals instead of anything that has the potential to be global. – Daniel Naab Aug 12 '11 at 05:16
  • @Daniel, no it doesn't - make_tls_property, which is part of djangotoolbox, makes the property a per thread property! It's awesome and I use this trick to do virtual sites (hosting multiple domains in a single Django instance) on two different projects. Check it out! – Rob Osborne Aug 12 '11 at 11:55
  • @Rob Cool, I'll check it out. – Daniel Naab Aug 13 '11 at 06:57
2

One method is to simply write your own login view that calls the django-registration view to do the hard work, but passing it a different template depending on the context:

def login(request, *args, **kwargs):
    my_kwargs = kwargs.copy()
    if <mobile condition>:
        my_kwargs['template_name'] = 'my_app/some_template.html'
    else:
        my_kwargs['template_name'] = 'my_app/some_other_template.html'

    from django.contrib import auth
    return auth.login(request, *args, **my_kwargs)
Daniel Naab
  • 22,690
  • 8
  • 54
  • 55