【问题标题】:Changing skin layer based on URL根据 URL 更改皮肤层
【发布时间】:2011-06-06 23:52:19
【问题描述】:

我正在创建一个具有“桌面”和“移动”主题的网站。我有这个站点的两个主题包:mysite.theme 和 mysite.mobile_theme。 mobile_theme 是桌面主题的精简版,具有新视图和精简的视图集。我想根据访问网站的 URL(即 mobile.mysite.com 与 www.mysite.com)在这两个主题之间切换。

由于移动和桌面主题将共享大量代码,mysite.mobile_theme 以下列方式从 mysite.theme 继承:

1) mobile_theme GS skins.xml有一个基于旧主题的皮肤路径,所以使用桌面主题的CSS等:

<skin-path name="mysite.mobile_theme" based-on="mysite.theme">

2) IThemeSpecific 标记是原始标记的子类,因此我不会为移动网站覆盖的视图回退到 mysite.theme 中的视图:

from mysite.theme.browser.interfaces import IThemeSpecific as IBaseTheme
class IThemeSpecific(IBaseTheme):
    """Marker interface that defines a Zope 3 browser layer.
    """

3) 我在 mysite.mobile_theme 中注册了各种视图以覆盖 mysite.theme 中的某些视图。

4) 我使用通用设置为每个主题设置不同的 viewlet 注册。

在这个阶段,如果我在“默认皮肤”选项门户皮肤->属性中选择 mysite.mobile_theme,一切正常:使用我的视图和来自 mobile_theme 的 GS 配置文件的视图设置被正确拾取。所以看起来主题的整体设置是正确的。

不过,如上所述,我想根据 URL 在这两个主题之间进行交换。

首先,我将“默认皮肤”换回“mysite.theme”。然后我在我的 Plone 站点的根目录中创建了一个 access_rule,大致遵循 these instructions 以根据 URL 选择皮肤。它位于 plonesite/access_rule 并设置为 plone 站点的 access_rule:

url = context.REQUEST.get('ACTUAL_URL', '')

if 'mobile' in url:
   context.changeSkin('mysite.mobile_theme', context.REQUEST)
else:
   context.changeSkin('mysite.theme', context.REQUEST)

我也尝试过使用context.REQUEST.set('plone_skin', 'mysite.theme'),而不是调用context.changeSkin(...)

使用此设置,显示的 viewlet 会根据我使用的 URL 正确更改 - 所以看起来皮肤在某些时候正在更改 - 但 mysite.mobile_theme 的视图类/模板没有被使用偏好 mysite.theme 的。总结:

  • 如果我从包含“mobile”的 URL 调用,我会得到 mysite.theme 的视图,但 mysite.mobile_theme 的 viewlet 注册。
  • 否则,我会得到 mysite.theme 的视图和 mysite.theme 的 viewlet 注册。

看起来我可能不得不挂钩到遍历机制来更改它,所以如果 URL 中有“mobile”,则选择针对其 IThemeSpecific 注册的 mysite.mobile_theme 的视图,而不是 mysite.theme 的视图,但我我不确定这是正确的,也不知道我会怎么做。

谁能给我一些指点?

在最初询问后 3 小时更新

回答我自己的问题(由于 SO 的规定,我不能再等 5 个小时):

""" 看来您必须在堆栈中打低得多的补丁才能完成这项工作。我在 plone.gomobile 中查看了它是如何完成的,他们对皮肤选择代码本身进行了猴子补丁。见:

http://code.google.com/p/plonegomobile/source/browse/gomobile.mobile/trunk/gomobile/mobile/monkeypatch.py """

【问题讨论】:

  • 记录在案:现在(2013 年)您可以制定仅在某些情况下应用的 CSS 规则。寻找“CSS 媒体查询”。使用该方法,您只需要一个 CSS 文件和一组 HTML。

标签: plone zope


【解决方案1】:

您可以使用collective.editskinswitcher。它的主要用例是使用例如 edit.example.com 上的 Plone Default 主题和 www.example.com 上的 My Custom Theme。不过,您可能可以调整其属性表以适合您的用例。

由于“移动主题”用例相当普遍,我会接受补丁以使其更容易;或者我可以自己研究一下。

(顺便说一句,请注意,当您错过为特定浏览器层注册的某些项目时,有一个 fix-browser-layers 分支可能会有所帮助;似乎已准备好合并,只是我想先添加一些测试。)

【讨论】:

  • 这个产品看起来可以满足我的需求。我特别喜欢使用 IBeforeTraverseEvent 而不是猴子补丁。将此回复标记为已接受的答案。
【解决方案2】:

我已经在一些移动主题原型中做到了这一点。请考虑这两个插件尚未准备好投入生产:

相关代码为:

【讨论】:

    【解决方案3】:

    我是否正确理解在移动 URL 上您的 皮肤 是正确的,但您的 Zope3 视图不正确?这对我来说很有意义,因为视图类是基于接口的。在上面的相同代码中,您使用context.changeSkin,添加:

    from zope.interface import alsoProvides
    alsoProvides(context, IMobileView)
    

    并让您的视图 zcml 指定 for ... IMobileView

    [编辑:再想一想,这真的应该是当你改变皮肤时发生的事情——额外的界面将是你的“IThemeSpecific”——所以我不确定这里有什么在起作用,但它不会受到伤害试试alsoProvides(context, IThemeSpecific)]

    【讨论】:

    • 我尝试将它添加到我的 access_rule(这是一个脚本 (Python) 对象,因此我需要取消限制某些模块)。不幸的是,这对我的结果没有任何影响。
    猜你喜欢
    • 2014-08-23
    • 2014-12-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-28
    • 1970-01-01
    • 2023-04-10
    • 2015-04-18
    相关资源
    最近更新 更多