根据用户代理更改Django模板

时间:2020-03-06 15:02:56  来源:igfitidea点击:

我已经创建了Django网站,但是我喝了Koolaid,并且想要创建iPhone版本。经过深思熟虑之后,我提出了两种选择:

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

但是,我真的更喜欢选择#2. 我有所保留,主要是因为Django文档不鼓励动态更改设置。我发现了一个片段,可以满足我的需求。我的主要问题是让它尽可能地无缝,我希望它对用户是自动的和透明的。

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

更新

我结合了中间件和调整模板调用。

对于中间件,我使用了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')
  • 如果不存在移动版本,则使用以前的版本自动回退到常规模板。

解决方案

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

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

我们应该看一下django-mobileadmin源代码,它完全解决了这个问题。

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

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

我正在开发Django移动扩展djangobile:http://code.google.com/p/djangobile/

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

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

本文可能很有用:15分钟内在Django中构建移动和桌面友好的应用程序

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

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

从Django文档中:

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

最佳方案:使用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>