40

我做了一个 Django 网站,但我喝了 Koolaid,我想做一个iPhone版本。经过深思熟虑,我提出了两个选择:

  1. 制作一个完整的其他网站,例如 i.xxxx.com。使用 Django 的站点框架将其绑定到同一个数据库中。
  2. 找一些中间件读取用户代理,并动态更改模板目录。

但是,我真的更喜欢选项#2;我有一些保留意见,主要是因为 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')
  • 如果不存在移动版本,则使用以前的自动回退到常规模板。
4

9 回答 9

20

您可以修改请求并添加一个值,让您的视图知道用户是否在 iphone 上,而不是动态更改模板目录。然后包装 render_to_response (或您用于创建 HttpResponse 对象的任何内容)以获取模板的 iphone 版本,而不是标准的 html 版本(如果他们使用的是 iphone)。

于 2008-10-02T20:44:38.020 回答
14

检测中间件中的用户代理,切换url绑定,获利!

如何?Django 请求对象有一个 .urlconf 属性,可以由中间件设置。

来自 django 文档:

Django 确定要使用的根 URLconf 模块。通常,这是 ROOT_URLCONF 设置的值,但如果传入的 HttpRequest 对象具有名为 urlconf 的属性(由中间件请求处理设置),则将使用其值代替 ROOT_URLCONF 设置。

  1. 在 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"
    
  2. 不要忘记将其添加到 settings.py 中的 MIDDLEWARE_CLASSES 中:

    MIDDLEWARE_CLASSES= [...
        'yourproj.middleware.MobileMiddleware',
    ...]
    
  3. 创建一个移动 urlconf,yourproj/mobile_urls.py:

    urlpatterns=patterns('',('r'/?$', 'mobile.index'), ...)
    
于 2010-08-15T11:57:53.370 回答
3

我正在开发 djangobile,一个 django 移动扩展:http ://code.google.com/p/djangobile/

于 2008-10-19T12:46:33.280 回答
2

你应该看看django-mobileadmin源代码,它正好解决了这个问题。

于 2008-10-09T22:00:13.650 回答
2

其他方式是创建您自己的模板加载器来加载特定于用户代理的模板。这是一种非常通用的技术,可用于根据其他因素动态确定必须加载的模板,例如请求的语言(现有 Django i18n 机器的良好伴侣)。

Django Book 有一个关于这个主题的部分

于 2008-10-16T09:41:23.410 回答
2

有一篇很好的文章解释了如何通过不同的模板呈现相同的数据 http://www.postneo.com/2006/07/26/acknowledgeing-the-mobile-web-with-django

但是,您仍然需要自动将用户重定向到移动网站,这可以使用多种方法完成(您的 check_mobile 技巧也可以)

于 2008-11-18T19:06:33.953 回答
1

在某些中间件中解析用户的 UA 后将用户重定向到 i.xxx.com 怎么样?我非常怀疑移动用户是否关心 url 的外观,他们仍然可以使用主 url 访问您的网站。

于 2008-10-02T21:08:31.410 回答
1

最佳可能方案:使用 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>
于 2010-11-11T07:43:09.383 回答
0

一个简单的解决方案是围绕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')
于 2013-01-24T21:09:45.207 回答