我做了一个Django的网站,但我已经喝了Koolaid,我想打一个IPhone版本。 把过多考虑到我已经拿出两个选项后:
- 做一个整体的其他网站,如i.xxxx.com。 扎入使用Django的站点框架相同的数据库。
- 查找中间件的一段时间,读取用户代理,且动态地改变模板目录。
我真的很喜欢选项#2,但是, 我有一些保留意见,主要是因为Django文档不鼓励在飞行中更改设置 。 我发现了一个片段 ,会做的想我。 我的主要问题是有它尽可能地无缝,我想它是AUTOMAGIC和对用户透明。
有没有其他人遇到了同样的问题? 有没有人愿意分享有关他们是如何解决使Django的网站IPhone版本?
更新
我去与中间件的组合和调整模板调用。
对于中间件,我用minidetector 。 我喜欢它,因为它检测到大量的移动用户代理的。 所有我需要做的就是在我的观点检查request.mobile。
对于调用模板的调整:
def check_mobile(request, template_name):
if request.mobile:
return 'mobile-%s'%template_name
return template_name
我用这个,我知道我有两个版本的任何观点。
ALL:
- 弄清楚如何访问request.mobile选择render_to_response中的扩展版本,所以我没有使用check_mobile(“template_name.html”)
- 使用前面自动地退回到常规模板,如果没有移动版本存在。
而不是更改模板目录的动态,你可以修改请求,并添加一个值,让您的视图知道,如果用户在iPhone或没有。 然后选择render_to_response包裹(或任何你正在使用创建的HttpResponse对象)抢模板,而不是标准的HTML版本的iphone版本,如果他们使用的是iPhone。
检测用户代理中间件,切换网址绑定,利润!
怎么样? Django的请求对象具有属性.urlconf,其可以通过中间件被设置。
从Django文档:
Django的确定根URL配置模块来使用。 通常,这是ROOT_URLCONF设置的值,但如果传入HttpRequest对象具有属性称为URL配置(由中间件请求处理设定)时,它的值将代替ROOT_URLCONF设置一起使用。
在yourproj / middlware.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'), ...)
本文可能是有用的: 建立在15分钟在Django移动和桌面友好的应用程序
我正在开发djangobile,Django的移动扩展: http://code.google.com/p/djangobile/
你应该看看Django的mobileadmin源代码,这正好解决了这个问题。
另一个方法是先创建加载特定于用户代理模板自己的模板加载器。 这是非常通用的技术,可以用动态地确定具有取决于其他因素要加载太像请求的语言(好伴侣现有的Django的i18n机械)什么模板。
Django的书有一个关于这个问题的部分 。
有一个很好的文章,解释如何使不同的模板相同的数据http://www.postneo.com/2006/07/26/acknowledging-the-mobile-web-with-django
你仍然需要但是,自动将用户重定向到移动网站,这可以使用多种方法来完成(您check_mobile伎俩将工作太)
怎么样在一些中间件解析他的UA后重定向用户i.xxx.com? 我高度怀疑,移动用户怎么在意网址的样子,他们仍然可以使用主URL访问你的网站。
最好的情况下:使用minidetector到额外的信息添加到请求,然后使用内置的请求上下文Django的将它传递给你的模板,像这样
from django.shortcuts import render_to_response
from django.template import RequestContext
def my_view_on_mobile_and_desktop(request)
.....
render_to_response('regular_template.html',
{'my vars to template':vars},
context_instance=RequestContext(request))
然后在模板中,您能介绍的东西,如:
<html>
<head>
{% block head %}
<title>blah</title>
{% if request.mobile %}
<link rel="stylesheet" href="{{ MEDIA_URL }}/styles/base-mobile.css">
{% else %}
<link rel="stylesheet" href="{{ MEDIA_URL }}/styles/base-desktop.css">
{% endif %}
</head>
<body>
<div id="navigation">
{% include "_navigation.html" %}
</div>
{% if not request.mobile %}
<div id="sidebar">
<p> sidebar content not fit for mobile </p>
</div>
{% endif %>
<div id="content">
<article>
{% if not request.mobile %}
<aside>
<p> aside content </p>
</aside>
{% endif %}
<p> article content </p>
</aricle>
</div>
</body>
</html>
一个简单的解决方案是创建一个围绕包装django.shortcuts.render
。 我把我的一个utils
图书馆在我的应用程序的根。 包装器的工作原理是在任何一个“移动”或“桌面”文件夹自动呈现模板。
在utils.shortcuts
:
from django.shortcuts import render from user_agents import parse def my_render(request, *args, **kwargs): """ An extension of django.shortcuts.render. Appends 'mobile/' or 'desktop/' to a given template location to render the appropriate template for mobile or desktop depends on user_agents python library https://github.com/selwin/python-user-agents """ template_location = args[0] args_list = list(args) ua_string = request.META['HTTP_USER_AGENT'] user_agent = parse(ua_string) if user_agent.is_mobile: args_list[0] = 'mobile/' + template_location args = tuple(args_list) return render(request, *args, **kwargs) else: args_list[0] = 'desktop/' + template_location args = tuple(args_list) return render(request, *args, **kwargs)
在view
:
from utils.shortcuts import my_render def home(request): return my_render(request, 'home.html')