基于User-Agent更改Django模板

时间:2008-10-02 20:30:09

标签: python django django-templates mobile-website django-middleware

我创建了一个Django网站,但我喝了Koolaid,我想制作一个 IPhone 版本。经过深思熟虑之后,我提出了两个选择:

  1. 制作整个其他网站,例如i.xxxx.com。使用Django的站点框架将其绑定到同一个数据库中。
  2. 找一些读取用户代理的中间件,并动态更改模板目录。
  3. 然而,我真的更喜欢选项#2;我有一些保留意见,主要是因为Django文档discourages changing settings on the fly。我找到了snippet,可以按照我的意愿行事。我的主要问题是让它尽可能无缝,我希望它对用户来说是自动化和透明的。

    还有其他人遇到同样的问题吗?是否有人愿意分享他们如何解决制作iPhone版Django网站的问题?

    更新

    我使用了中间件和调整模板调用的组合。

    对于中间件,我使用minidetector。我喜欢它,因为它检测到plethora个移动用户代理。我所要做的就是在我的观点中检查request.mobile。

    对于模板调用调整:

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

    我将此用于任何我知道我有两个版本的视图。

    TODO:

    • 了解如何在render_to_response的扩展版本中访问 request.mobile ,这样我就不必使用check_mobile('template_name.html')
    • 如果不存在移动版本,请使用之前的自动回退到常规模板。

10 个答案:

答案 0 :(得分:20)

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

答案 1 :(得分:11)

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

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

来自django docs:

  

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'), ...)
    

答案 2 :(得分:4)

答案 3 :(得分:3)

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

答案 4 :(得分:2)

您应该查看django-mobileadmin源代码,它解决了这个问题。

答案 5 :(得分:2)

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

Django Book有section on this subject

答案 6 :(得分:2)

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

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

答案 7 :(得分:1)

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

答案 8 :(得分: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>

答案 9 :(得分: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')