views:

3399

answers:

8

I've made a Django site, but I've drank the Koolaid and I want to make an IPhone version. After putting much thought into I've come up with two options:

  1. Make a whole other site, like i.xxxx.com. Tie it into the same database using Django's sites framework.
  2. Find some time of middleware that reads the user-agent, and changes the template directories dynamically.

I'd really prefer option #2, however; I have some reservations, mainly because the Django documentation discourages changing settings on the fly. I found a snippet that would do the what I'd like. My main issue is having it as seamless as possible, I'd like it to be automagic and transparent to the user.

Has anyone else come across the same issue? Would anyone care to share about how they've tackled making IPhone versions of Django sites?

Update

I went with a combination of middleware and tweaking the template call.

For the middleware, I used minidetector. I like it because it detects a plethora of mobile user-agents. All I have to do is check request.mobile in my views.

For the template call tweak:

 def check_mobile(request, template_name):
     if request.mobile:
         return 'mobile-%s'%template_name
     return template_name

I use this for any view that I know I have both versions.

TODO:

  • Figure out how to access request.mobile in an extended version of render_to_response so I don't have to use check_mobile('template_name.html')
  • Using the previous automagically fallback to the regular template if no mobile version exists.
+10  A: 

Rather than changing the template directories dynamically you could modify the request and add a value that lets your view know if the user is on an iphone or not. Then wrap render_to_response (or whatever you are using for creating HttpResponse objects) to grab the iphone version of the template instead of the standard html version if they are using an iphone.

ordord00
probably the best way to go...I just didn't want to have to add extra code to my views.thanks for the answer!
jobscry
What I do is write my own render_to_response wrapper and put it in an project wide utilities library. Then just import that instead of render_to_response (like my_render_response). You have the same amount of code in your views and just have to change up the import and func call in your views.
ordord00
+1  A: 

How about redirecting user to i.xxx.com after parsing his UA in some middleware? I highly doubt that mobile users care how url look like, still they can access your site using main url.

Dmitry Shevchenko
How does this help? You still have the template names and layouts for the site. Either you create a whole new set of logic, or the problem persists.
Mark0978
+2  A: 

You should take a look at the django-mobileadmin source code, which solved exactly this problem.

ak
+2  A: 

Other way would be creating your own template loader that loads templates specific to user agent. This is pretty generic technique and can be use to dynamically determine what template has to be loaded depending on other factors too, like requested language (good companion to existing Django i18n machinery).

Django Book has a section on this subject.

zgoda
+3  A: 

I'm developing djangobile, a django mobile extension: http://code.google.com/p/djangobile/

+2  A: 

There is a nice article which explains how to render the same data by different templates http://www.postneo.com/2006/07/26/acknowledging-the-mobile-web-with-django

You still need to automatically redirect the user to mobile site however and this can be done using several methods (your check_mobile trick will work too)

Amit
+4  A: 

This article might be useful: Build a Mobile and Desktop-Friendly Application in Django in 15 Minutes

Swaroop C H
+1  A: 

Detect the user agent in middleware, switch the url bindings, profit!

How? Django request objects have a .urlconf attribute, which can be set by middleware.

From django docs:

Django determines the root URLconf module to use. Ordinarily, this is the value of the ROOT_URLCONF setting, but if the incoming HttpRequest object has an attribute called urlconf (set by middleware request processing), its value will be used in place of the ROOT_URLCONF setting.

  1. In yourproj/middlware.py, write a class that checks the http_user_agent string:
import re
MOBILE_AGENT_RE=re.compile(r".*(iphone|mobile|androidtouch)",re.IGNORECASE)
class MobileMiddleware(object):
def process_request(self,request):
    if MOBILE_AGENT_RE.match(request.META['HTTP_USER_AGENT']):
        request.urlconf="yourproj.mobile_urls"
  1. Don't forget to add this to MIDDLEWARE_CLASSES in settings.py:

    MIDDLEWARE_CLASSES= [... 'yourproj.middleware.MobileMiddleware', ...]

  2. Create a mobile urlconf, yourproj/mobile_urls.py:

    urlpatterns=patterns('',('r'/?$', 'mobile.index'), ...)

am