根据用户代理更改 Django 模板
-
03-07-2019 - |
题
我已经制作了一个 Django 网站,但我喝了 Koolaid,我想制作一个 IPhone 版本。经过深思熟虑,我提出了两个选择:
- 创建一个完整的其他网站,例如 i.xxxx.com。使用 Django 的站点框架将其绑定到同一个数据库中。
- 找到一些读取用户代理并动态更改模板目录的中间件。
然而,我真的更喜欢选项#2;我有一些保留,主要是因为Django文档 不鼓励动态更改设置. 。我找到了一个 片段 那会做我想做的事。我的主要问题是让它尽可能无缝,我希望它对用户来说是自动且透明的。
还有其他人遇到过同样的问题吗?有人愿意分享一下他们是如何制作 iPhone 版本的 Django 网站的吗?
更新
我结合使用了中间件并调整了模板调用。
对于中间件,我使用了 微型探测器. 。我喜欢它,因为它检测到 过多 移动用户代理。我所要做的就是在我的视图中检查 request.mobile 。
对于模板调用调整:
def check_mobile(request, template_name):
if request.mobile:
return 'mobile-%s'%template_name
return template_name
我将其用于任何我知道我有两个版本的视图。
去做:
- 了解如何访问 请求.mobile 在 render_to_response 的扩展版本中,所以我不必使用 check_mobile('template_name.html')
- 如果不存在移动版本,则使用之前的自动回退到常规模板。
解决方案
您可以修改请求并添加一个值,让您的视图知道用户是否使用 iPhone,而不是动态更改模板目录。然后包装 render_to_response (或用于创建 HttpResponse 对象的任何内容)以获取模板的 iphone 版本,而不是标准 html 版本(如果他们使用的是 iphone)。
其他提示
检测中间件中的用户代理,切换url绑定,盈利!
如何?Django 请求对象有一个 .urlconf 属性,可以通过中间件设置。
来自 django 文档:
Django确定要使用的根URLCONF模块。通常,这是 ROOT_URLCONF设置的值,但 如果传入的 HttpRequest 对象具有 一个名为 urlconf 的属性(由 中间件请求处理)、其 value 将用于代替 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 的样子,但他们仍然可以使用主 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')