制作Zope网站页面内容的简单方法
项目描述
largeblue.pages旨在解决一个相当常见、相对简单的Web开发需求
网站的页面全部或部分需要通过WYSIWYG编辑器进行编辑(例如:由客户或非技术网站管理员进行)
但是,网站的开发者(们)绝对不希望通过WYSIWYG编辑器编辑页面的内容,他们(你)想使用他们(你)的正常文本编辑器,并可能使用版本控制等。
网站的一些页面可能不适合通过WYSIWYG进行编辑(例如:在特定页面的特定标记结构上使用javascript)
网站结构应该是灵活的,以便可以递归地添加新页面和部分,而无需重新开发
largeblue.pages
提供页面容器和页面内容对象,其中页面可以包含任意数量的子页面,等等
页面的内容属性被设置为可以通过WYSIWYG编辑器进行编辑(实际上,我们配置并修补了默认的z3c.widget.tiny WYSIWYG小部件,以确保它存储有效的xhtml,并且输出源代码的嵌套每个元素缩进2个空格)
每个页面及其HTML内容也可以通过WebDAV访问(largeblue.pages使用bebop.webdav对zope.app.dav / z3c.dav的修补来提供读写WebDAV访问),因此页面看起来像文件夹,包含一个main_content.html和任意数量的其他页面文件夹。这样,可以在不接近网页浏览器的情况下编辑整个页面结构。
还有一些其他有用的功能
@@edit.html和@@ordering.html是自定义ZMI视图,可以挂载在页面上,添加到管理皮肤中,其中@@ordering.html(称为“管理内容”)基于largeblue.order提供了一个自定义的可排序容器视图,因此可以移动页面上下、重命名、剪切粘贴、删除和添加等。
每个页面容器都有一个名为“index”的属性,它包含当前页面结构的快照(每当创建、修改或删除页面事件发生时都会更新)——请注意,可以拥有多个页面容器,因为它们都维护自己的索引
每个页面的obj.__name__被强制为没有跨浏览器href问题的文本片段
页面有一个标志属性,旨在在视图类中引用(参见./browser/index.py),以控制它们是“简单”页面(仅渲染可管理的内容)还是需要特殊处理的定制页面
要使用largeblue.pages,只需将包添加到您的site.zcml(或等效文件)中(包括largeblue.pages包和include overrides.zcml作为覆盖)。
无论如何,让我们看看它的工作情况。
>>> import transaction, pprint >>> from zope.component import createObject >>> from zope.event import notify >>> from zope.lifecycleevent import ObjectCreatedEvent >>> from zope.lifecycleevent import ObjectModifiedEvent >>> from bebop.ordering.interfaces import IOrdering, IOrderable >>> from largeblue.pages.interfaces import IPage, IPageContainer, IFile >>> from largeblue.pages.page import PageContainer
创建一个页面容器。
>>> app['pages'] = PageContainer()
创建一个页面。
>>> page1 = createObject('largeblue.pages.Page') >>> page1.__name__ = 'page1' >>> page1.title = u'Page 1' >>> for item in page1: ... print item ... >>> page1.content u'' >>> page1.flag u'Static'
将其添加到容器中并触发创建事件。
>>> app['pages']['page1'] = page1 >>> notify(ObjectCreatedEvent(page1))
现在我们看到它包含一个名为html_content.html的文件,并且可以通过页面的内容属性进行编辑。
>>> page1 = app['pages']['page1'] >>> for item in page1: ... print item ... main_content.html >>> page1['main_content.html'].contentType 'text/html' >>> page1.content '<div>Under construction</div>' >>> page1['main_content.html'].data '<div>Under construction</div>' >>> page1['main_content.html'].data = '<div>Foo bar</div>' >>> page1['main_content.html'].data '<div>Foo bar</div>' >>> page1.content '<div>Foo bar</div>' >>> page1.content = '<div>Under construction</div>' >>> page1.content '<div>Under construction</div>' >>> page1['main_content.html'].data '<div>Under construction</div>'
让我们看看页面容器的index属性。
>>> pages = app['pages'] >>> for item in pages: ... print item ... page1 >>> pages.index [{'title': u'Page 1', 'pages': [], 'label': u'page1'}] >>> page2 = createObject('largeblue.pages.Page') >>> page2.__name__ = 'movies' >>> page2.title = u'Movies' >>> pages['movies'] = page2 >>> for item in pages: ... print item ... movies page1 >>> notify(ObjectCreatedEvent(page2)) >>> pages.index [{'title': u'Page 1', 'pages': [], 'label': u'page1'}, {'title': u'Movies', 'pages': [], 'label': u'movies'}]
我们可以在页面内部嵌套页面。
>>> page3 = createObject('largeblue.pages.Page') >>> page3.__name__ = 'horror' >>> page3.title = u'Scary Horror Films' >>> notify(ObjectCreatedEvent(page3)) >>> pages['movies']['horror'] = page3 >>> page4 = createObject('largeblue.pages.Page') >>> page4.__name__ = 'texas' >>> page4.title = u'The Texas Chainsaw Massacre' >>> notify(ObjectCreatedEvent(page4)) >>> pages['movies']['horror']['texas'] = page4
再次检查索引。
>>> pprint.pprint(pages.index) [{'title': u'Page 1', 'pages': [], 'label': u'page1'}, {'label': u'movies', 'pages': [{'label': u'horror', 'pages': [{'label': u'texas', 'pages': [], 'title': u'The Texas Chainsaw Massacre'}], 'title': u'Scary Horror Films'}], 'title': u'Movies'}]
目的是让索引可以被动态导航引用,例如,不必每次都遍历页面的层次结构。关键是可以对页面进行排序,这样就可以控制导航项的显示顺序。
我们已经修补了bebop.ordering来实现这一点。让我们看看根容器的排序。
>>> IOrdering(pages).getNames() [u'page1', u'movies'] >>> IOrdering(pages).keys() [0, 1] >>> IOrdering(pages).upOne([1]) >>> IOrdering(pages).getNames() [u'movies', u'page1'] >>> notify(ObjectModifiedEvent(pages)) >>> pprint.pprint(pages.index) [{'label': u'movies', 'pages': [{'label': u'horror', 'pages': [{'label': u'texas', 'pages': [], 'title': u'The Texas Chainsaw Massacre'}], 'title': u'Scary Horror Films'}], 'title': u'Movies'}, {'title': u'Page 1', 'pages': [], 'label': u'page1'}]
有关此内容的更多信息,请参阅largeblue.order.README.txt,基本上我们所做的就是将排序容器的可排序内容限制为仅包括页面
>>> for item in page3: ... print item ... main_content.html texas >>> IOrdering(page3).getNames() [u'texas']
此外,我们还扩展了排序容器视图的功能,以适应“正常”操作。这样,管理员皮肤ZMI层只需在页面上公开@@edit.html和@@ordering.html视图,从而在页面容器视图中隐藏除页面之外的所有内容(例如:main_content.html、.svn文件等)。
要通过WebDAV连接到页面结构,只需连接到您的站点实例,例如:https://127.0.0.1:8080,然后,哇,您将看到如下结构
pages
page1
main_content.html
movies
main_content.html
texas
main_content.html
编辑main_content.html文件以编辑页面的主要内容。但是要小心——不要重命名它,也不要保存无效的xhtml。目的是只有知道这些的合格开发人员才能获得WebDAV访问权限。