Python 基于用户代理更改Django模板
我已经制作了一个Django网站,但我已经喝了Kooled,我想制作一个IPhone版本。经过深思熟虑,我想出了两个选择:Python 基于用户代理更改Django模板,python,django,django-templates,mobile-website,django-middleware,Python,Django,Django Templates,Mobile Website,Django Middleware,我已经制作了一个Django网站,但我已经喝了Kooled,我想制作一个IPhone版本。经过深思熟虑,我想出了两个选择: 创建一个完整的其他网站,如i.xxxx.com。使用Django的sites框架将其绑定到同一个数据库中 找一段时间的中间件来读取用户代理,并动态更改模板目录 然而,我真的更喜欢选项2;我有一些保留,主要是因为Django文档。我找到了一个可以做我想做的事的。我的主要问题是让它尽可能无缝,我希望它是自动和透明的用户 还有其他人遇到过同样的问题吗?有没有人愿意分享一下他们是如
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')
- 如果不存在移动版本,则使用以前的自动回退到常规模板
Django的书有一个。我正在开发djangobile,一个Django移动扩展:有一篇很好的文章,解释了如何通过不同的模板呈现相同的数据
但是,您仍然需要自动将用户重定向到移动站点,这可以使用多种方法完成(您的check_mobile技巧也会起作用)在中间件中检测用户代理,切换url绑定,获利 怎么做?Django请求对象有一个.urlconf属性,可以由中间件设置 来自django文档: Django确定根URLconf 要使用的模块。通常,这是 ROOT_URLCONF设置的值,但 如果传入的HttpRequest对象 一个名为urlconf的属性(由 中间件(请求处理) 将使用值来代替 ROOT\u URLCONF设置
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"
MIDDLEWARE_CLASSES= [...
'yourproj.middleware.MobileMiddleware',
...]
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>
{%block head%}
废话
{%if request.mobile%}
{%else%}
{%endif%}
{%include“_navigation.html”%}
{%if not request.mobile%}
侧边栏内容不适合移动设备
{%endif%>
{%if not request.mobile%}
旁白内容
{%endif%}
文章内容
一个简单的解决方案是围绕django.shortcuts.render
创建一个包装器。我将我的包装器放在我的应用程序根目录下的utils
库中。包装器通过在“mobile”或“desktop”文件夹中自动呈现模板来工作
在utils.shortcuts
中:
在视图中
:
可能是最好的方法…我只是不想在视图中添加额外的代码。谢谢你的回答!我要做的是编写自己的render\u to\u响应包装器,并将其放入项目范围的实用程序库中。然后只需导入它而不是render\u to\u响应(如我的render\u响应)。您的视图中有相同数量的代码,只需更改视图中的导入和func调用即可。@imjoevasquez这是事后的做法,但您始终可以从my_site\u wide\u stuff执行类似于
的操作。utils将my_render\u to_response导入为render\u to_response
-因为render\u to_response
只是一种快捷方式nyways。虽然查找/替换可能是一种方法;)如果我试图根据移动设备或桌面在DOM的不同位置呈现模板,您会推荐相同的方法吗?您也可以这样做/需要这样做,以拥有一个特殊的IE6版本的模板。我考虑使用1个模板,如果用户代理s IE6。我喜欢你这样做:)你会说我有太多的Pinata吗?请注意,不幸的是,minidetector似乎与Python 3不兼容。请参阅以获取替代方案。这有什么帮助?你仍然有网站的模板名称和布局。或者你创建了一整套新的逻辑,或者问题仍然存在。
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 utils.shortcuts import my_render
def home(request): return my_render(request, 'home.html')