根据用户代理改变Django模板
我做了一个Django网站,但我想做一个iPhone版本。经过一番思考,我想出了两个选择:
- 做一个完全不同的网站,比如i.xxxx.com。然后用Django的站点框架把它和同一个数据库连接起来。
- 找一种中间件,能够读取用户代理(user-agent),并动态改变模板目录。
我更倾向于第二个选项,不过我有一些顾虑,主要是因为Django的文档不鼓励动态改变设置。我找到了一段代码片段,可以实现我想要的功能。我的主要问题是希望这个过程尽可能无缝,让用户感觉不到任何变化。
有没有人遇到过类似的问题?有人愿意分享一下他们是如何制作Django网站的iPhone版本的吗?
更新
我选择了中间件和调整模板调用的组合。
在中间件方面,我使用了minidetector。我喜欢它,因为它可以检测到很多移动设备的用户代理。我的视图中只需要检查request.mobile。
关于模板调用的调整:
def check_mobile(request, template_name):
if request.mobile:
return 'mobile-%s'%template_name
return template_name
我在任何我知道有两个版本的视图中使用这个。
待办事项:
- 弄清楚如何在扩展的render_to_response中访问request.mobile,这样我就不需要使用check_mobile('template_name.html')
- 使用之前的方法,如果没有移动版本,自动回退到常规模板。
9 个回答
我正在开发一个叫做djangobile的项目,这是一个Django的移动扩展:http://code.google.com/p/djangobile/
在中间件中检测用户代理,切换网址绑定,赚到钱!
怎么做呢?Django的请求对象有一个叫做.urlconf的属性,这个属性可以通过中间件来设置。
根据Django的文档:
Django会确定使用哪个根URL配置模块。通常,这个模块的值是ROOT_URLCONF设置的值,但如果传入的HttpRequest对象有一个叫做urlconf的属性(这个属性是通过中间件处理请求时设置的),那么它的值将会替代ROOT_URLCONF的设置。
在你的项目目录下的middleware.py文件中,写一个类来检查http_user_agent字符串:
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"
别忘了在settings.py中把这个类添加到MIDDLEWARE_CLASSES里:
MIDDLEWARE_CLASSES= [... 'yourproj.middleware.MobileMiddleware', ...]
创建一个移动设备的urlconf,文件名为yourproj/mobile_urls.py:
urlpatterns=patterns('',('r'/?$', 'mobile.index'), ...)
与其动态地改变模板目录,不如直接修改请求,添加一个值来告诉你的视图用户是否在使用iPhone。然后,你可以把render_to_response(或者你用来创建HttpResponse对象的其他方法)包裹起来,这样如果用户使用的是iPhone,就能获取到iPhone版本的模板,而不是普通的HTML版本。