python 基于 User-Agent 更改 Django 模板
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/164427/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Change Django Templates Based on User-Agent
提问by imjoevasquez
I've made a Django site, but I've drank the Koolaid and I want to make an IPhoneversion. After putting much thought into I've come up with two options:
我已经创建了一个 Django 站点,但是我喝了 Koolaid 并且我想创建一个iPhone版本。经过深思熟虑,我想出了两个选择:
- Make a whole other site, like i.xxxx.com. Tie it into the same database using Django's sites framework.
- Find some time of middleware that reads the user-agent, and changes the template directories dynamically.
- 制作一个完整的其他网站,例如 i.xxxx.com。使用 Django 的站点框架将其绑定到同一个数据库中。
- 找一些时间读取用户代理的中间件,并动态更改模板目录。
I'd really prefer option #2, however; I have some reservations, mainly because the Django documentation discourages changing settings on the fly. I found a snippetthat would do the what I'd like. My main issue is having it as seamless as possible, I'd like it to be automagic and transparent to the user.
然而,我真的更喜欢选项#2;我有一些保留意见,主要是因为 Django 文档不鼓励即时更改设置。我找到了一个可以做我想做的事情的片段。我的主要问题是让它尽可能无缝,我希望它对用户来说是自动的和透明的。
Has anyone else come across the same issue? Would anyone care to share about how they've tackled making IPhone versions of Django sites?
有没有其他人遇到过同样的问题?有没有人愿意分享一下他们是如何制作 Django 网站的 iPhone 版本的?
Update
更新
I went with a combination of middleware and tweaking the template call.
我结合了中间件和调整模板调用。
For the middleware, I used minidetector. I like it because it detects a plethoraof mobile user-agents. All I have to do is check request.mobile in my views.
对于中间件,我使用了minidetector。我喜欢它,因为它检测到大量的移动用户代理。我所要做的就是在我的视图中检查 request.mobile。
For the template call tweak:
对于模板调用调整:
def check_mobile(request, template_name):
if request.mobile:
return 'mobile-%s'%template_name
return template_name
I use this for any view that I know I have both versions.
我将它用于任何我知道我有两个版本的视图。
TODO:
去做:
- Figure out how to access request.mobilein an extended version of render_to_response so I don't have to use check_mobile('template_name.html')
- Using the previous automagically fallback to the regular template if no mobile version exists.
- 弄清楚如何在 render_to_response 的扩展版本中访问request.mobile,这样我就不必使用 check_mobile('template_name.html')
- 如果不存在移动版本,则使用以前的自动回退到常规模板。
采纳答案by Aaron
Rather than changing the template directories dynamically you could modify the request and add a value that lets your view know if the user is on an iphone or not. Then wrap render_to_response (or whatever you are using for creating HttpResponse objects) to grab the iphone version of the template instead of the standard html version if they are using an iphone.
您可以修改请求并添加一个值,让您的视图知道用户是否在 iphone 上,而不是动态更改模板目录。然后包装 render_to_response (或任何您用于创建 HttpResponse 对象的内容)以获取模板的 iphone 版本而不是标准 html 版本(如果他们使用的是 iphone)。
回答by Aneil Mallavarapu
Detect the user agent in middleware, switch the url bindings, profit!
检测中间件中的用户代理,切换url绑定,获利!
How? Django request objects have a .urlconf attribute, which can be set by middleware.
如何?Django 请求对象有一个 .urlconf 属性,可以由中间件设置。
From django docs:
来自 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.
Django 确定要使用的根 URLconf 模块。通常,这是 ROOT_URLCONF 设置的值,但如果传入的 HttpRequest 对象具有称为 urlconf 的属性(由中间件请求处理设置),则将使用其值代替 ROOT_URLCONF 设置。
In yourproj/middlware.py, write a class that checks the http_user_agent string:
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"
Don't forget to add this to MIDDLEWARE_CLASSES in settings.py:
MIDDLEWARE_CLASSES= [... 'yourproj.middleware.MobileMiddleware', ...]
Create a mobile urlconf, yourproj/mobile_urls.py:
urlpatterns=patterns('',('r'/?$', 'mobile.index'), ...)
在 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'), ...)
回答by Swaroop C H
This article might be useful: Build a Mobile and Desktop-Friendly Application in Django in 15 Minutes
这篇文章可能有用:在 15 分钟内在 Django 中构建一个移动和桌面友好的应用程序
回答by Swaroop C H
I'm developing djangobile, a django mobile extension: http://code.google.com/p/djangobile/
我正在开发 djangobile,一个 django 移动扩展:http: //code.google.com/p/djangobile/
回答by Amit
There is a nice article which explains how to render the same data by different templates http://www.postneo.com/2006/07/26/acknowledging-the-mobile-web-with-django
有一篇很好的文章解释了如何通过不同的模板呈现相同的数据 http://www.postneo.com/2006/07/26/acknowledging-the-mobile-web-with-django
You still need to automatically redirect the user to mobile site however and this can be done using several methods (your check_mobile trick will work too)
您仍然需要自动将用户重定向到移动站点,但这可以使用多种方法完成(您的 check_mobile 技巧也可以)
回答by ak.
You should take a look at the django-mobileadminsource code, which solved exactly this problem.
您应该查看django-mobileadmin源代码,它正好解决了这个问题。
回答by zgoda
Other way would be creating your own template loader that loads templates specific to user agent. This is pretty generic technique and can be use to dynamically determine what template has to be loaded depending on other factors too, like requested language (good companion to existing Django i18n machinery).
另一种方法是创建您自己的模板加载器,加载特定于用户代理的模板。这是一种非常通用的技术,可用于根据其他因素动态确定必须加载的模板,例如请求的语言(现有 Django i18n 机制的良好伴侣)。
Django Book has a section on this subject.
回答by Dmitry Shevchenko
How about redirecting user to i.xxx.com after parsing his UA in some middleware? I highly doubt that mobile users care how url look like, still they can access your site using main url.
在某些中间件中解析他的 UA 后,如何将用户重定向到 i.xxx.com?我非常怀疑移动用户是否关心 url 的外观,但他们仍然可以使用主 url 访问您的网站。
回答by Thomas
best possible scenario: use minidetector to add the extra info to the request, then use django's built in request context to pass it to your templates like so
最佳方案:使用 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))
then in your template you are able to introduce stuff like:
然后在您的模板中,您可以引入以下内容:
<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>
回答by Samora Dake
A simple solution is to create a wrapper around django.shortcuts.render
. I put mine in a utils
library in the root of my application. The wrapper works by automatically rendering templates in either a "mobile" or "desktop" folder.
一个简单的解决方案是围绕django.shortcuts.render
. 我把我的放在utils
我的应用程序根目录的一个库中。包装器通过在“移动”或“桌面”文件夹中自动呈现模板来工作。
In utils.shortcuts
:
在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)
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)
In view
:
在view
:
from utils.shortcuts import my_render def home(request): return my_render(request, 'home.html')
from utils.shortcuts import my_render def home(request): return my_render(request, 'home.html')