Django CMS 入门指南(二)

原文:Beginning Django CMS

协议:CC BY-NC-SA 4.0

八、在 django CMS 中创作

在前七章中,我们着重于设计我们的网站模板和探索 django CMS 的功能。在这一章中,我们将会把我们所学到的应用到实践中,为你的观众创造你的网站中最重要的部分:内容。

凭借前端编辑和灵活的插件架构,django CMS 为管理员和网站内容创建者提供了强大的内容格式化和编辑功能。

本章首先概述了 django CMS 工具栏及其功能。然后,我们将使用 django CMS 的内置插件,以及我们在上一章探讨的第三方插件,为您的网站创建三个页面——主页、关于页面和联系页面。一旦你的博客应用开始运行,我们还会为你创建一些博客文章,供你在后面的章节中使用。

在本章的后面,我们将详细探讨网站管理;特别是,我们将深入挖掘 Django 的auth.user模型,并将设置用户组和权限,这样我们的网站就像一个专业的 CMS——拥有适当的用户、作者、编辑和管理员角色以及仅限会员的内容。

django CMS 工具栏

django CMS 工具栏提供了对站点创作中所有重要功能的访问。

网站根目录(example.com)

网站的根菜单(图 8-1 )提供了页面和用户管理的快速链接,以及完整管理后端的链接。如果您没有在管理界面中更改默认的站点描述,它将被称为example.com。我将在本章的后面告诉你如何改变这一点。

A978-1-4842-1669-9_8_Fig1_HTML.jpg

图 8-1。

The django CMS root menu

这些菜单选项仅对拥有完全管理权限的用户可用。我们将在本章后面介绍管理功能。根菜单还允许任何注册用户(不仅仅是管理员)修改用户设置,包括管理界面中的默认语言,以及禁用工具栏。后者对于预览没有工具栏的网站很有用。

根菜单还提供对 django CMS 剪贴板的访问,剪贴板将包含最新复制的插件或最后创建的插件别名。

Tip

要重新启用工具栏,请返回编辑模式(/?edit)。

页面菜单(图 8-2 )提供对 django CMS 中所有页面管理功能的访问。

A978-1-4842-1669-9_8_Fig2_HTML.jpg

图 8-2。

The django CMS Page menu

添加页面

向 django CMS 添加页面有三个选项:

  • 新页面
  • 新建子页面
  • 复制此页

这些选项的页面设置是相同的,并通过弹出覆盖图进行设置(图 8-3 )。子页被添加到浏览器中当前选定的页面下;但是,这很容易更改(请参阅本章后面的页面管理部分)。所有这些设置都是不言自明的,添加页面应该没有问题。不要担心在这个阶段试图理解页面类型,因为我们很快就会讨论它。

A978-1-4842-1669-9_8_Fig3_HTML.jpg

图 8-3。

Adding new pages

django CMS 提供了开箱即用的基本页面设置集合;然而,页面模型是可扩展的。您将在第十章中学习如何扩展页面模型和添加额外的字段。

页面设置

页面设置菜单项提供与图 8-3 相同的设置。

模板

为页面选择一个模板。如果你遵循了第四章的说明,你应该有两个选择:页面和带侧边栏的博客页面。

高级设置

高级设置菜单允许您设置和修改许多高级页面设置(图 8-4 )。

  • 覆盖 URL。用页面的自定义 URL 替换系统生成的 URL。
  • 重定向。用于将旧页面重定向到新的 URL。也可用于重定向到外部 URL。
  • 模板。与在页面设置中更改页面模板的效果相同。
  • 身份证。这是一个超出本书范围的高级选项。它用于高级内部链接的模板标签中。
  • 软根。在此页面创建软根。用于创建子菜单;当附加到菜单时,被检查为软根的页面将不显示任何祖先。下一章将详细介绍菜单。
  • 附菜单。附加到此页面的自定义菜单。下一章将详细介绍菜单。
  • 申请。向 Django 应用提供 apphook。你将在第十章中了解 apphooks。
  • x 框架选项。设置页面是否可以嵌入到另一个页面中。用于防止您的网页在其他网站中被非法陷害。

A978-1-4842-1669-9_8_Fig4_HTML.jpg

图 8-4。

Page advanced settings

许可

可以通过权限菜单修改单个页面的权限(图 8-5 )。与全局用户和组权限相比,页面权限提供了更细粒度的页面控制。

A978-1-4842-1669-9_8_Fig5_HTML.jpg

图 8-5。

Page permissions

使用页面权限,您可以:

  • 要求用户登录才能访问该页面。
  • 隐藏菜单导航中的页面,只为特定用户显示菜单中的页面链接。
  • 限制某些用户和组查看该页面。
  • 添加或删除特定用户和组的页面编辑权限。

出版日期

发布日期菜单选项(图 8-6 )允许您设置页面发布的日期范围。可以为只在有限时间内显示的页面设置结束日期。

A978-1-4842-1669-9_8_Fig6_HTML.jpg

图 8-6。

Page publishing dates

在导航中隐藏

如果您不想在顶部菜单导航中显示页面,请选择此选项。

发布/取消发布页面

从出版物中发布或删除以前发布的页面。未发布的页面仅对编辑和管理员可见,并且不再出现在普通用户的导航菜单中。

删除页面

从 CMS 中删除页面。删除的页面可以在页面管理界面中恢复(请参阅本章后面的内容)。

另存为页面类型

页面类型是为特定类型的内容创建通用布局的非常有用的工具。例如,您可能有一个产品评论网站,其中每篇文章都有一张图片、一个摘要、详细信息,还可能有一个表格或选项卡来显示规格和建议。由于这种布局在您的网站上的所有产品评论中是通用的,但在一般的网站上不是通用的,所以您不希望修改网站模板。

将您的第一篇产品评论保存为页面类型可让您在所有产品评论中重复使用该格式。同样的原则也适用于您站点上任何想要复制格式或内容的内容。页面类型的另一个用途是在每篇文章的末尾有一个作者简介,在这里你不需要开发一个定制的插件。

请注意,当您第一次创建网站时,页面类型下拉列表是空的;没有默认的页面类型,您需要自己定义。

历史

django CMS 保留了对每个页面所做更改的详细历史记录。完整的页面历史可通过历史菜单访问(图 8-7 )。

A978-1-4842-1669-9_8_Fig7_HTML.jpg

图 8-7。

The History menu

History 菜单非常简单:有一个选项可以撤销当前的更改,也可以恢复到 live 版本,这将清除所有更改,恢复到当前发布的版本。

Caution

“恢复到实时”还会清除页面的所有已保存草稿。

查看历史将显示一个页面的完整历史(图 8-8 )。选择修订日期将为您提供恢复到所选修订的选项。

A978-1-4842-1669-9_8_Fig8_HTML.jpg

图 8-8。

Full page history

工具栏按钮

django CMS 工具栏的最后一个功能是工具栏按钮。这些按钮是上下文相关的,因此对于未发布的页面,工具栏看起来如图 8-9a ,而对于之前发布的页面,它看起来如图 8-9b 。“结构”和“内容”按钮提供了在编辑页面结构和编辑内容之间的轻松切换,“查看发布的”将从页面的草稿版本切换到当前发布的版本,“发布更改”就是这样做的:将当前页面发布到您的站点,以便所有用户都可以看到它(取决于页面权限)。

A978-1-4842-1669-9_8_Fig9b_HTML.jpg

图 8-9b。

The toolbar buttons for an unpublished page

A978-1-4842-1669-9_8_Fig9a_HTML.jpg

图 8-9a。

The toolbar buttons for an unpublished page

一旦你开始编辑,django CMS 会自动保存任何页面的草稿。这对于对页面进行较大的更改,或者当其他用户必须在发布更改之前批准更改时特别有用,因为在发布之前,除了编辑和管理员之外,其他所有人都看不到任何更改。这是对 WordPress 等 CMSes 的一大改进,在 WordPress 中,一旦页面发布,你就不能保存页面的编辑草稿。

Create 按钮启动 django CMS 内容创建向导。在默认安装中,可用的向导用于创建页面和子页面。它们的功能与页面创建工具栏选项的功能相同。

Note

django CMS 内容创建向导是 3.2 版的新增功能。可以使用类似于菜单和 apphooks 的注册过程将你自己的向导添加到 django CMS 中。向导超出了本书的范围,但是如果您想探索如何创建它们,请参见:

http://docs.django-cms.org/en/develop/how_to/wizards.html

向您的网站添加内容

既然您已经了解了所有可用的不同插件并探索了工具栏,那么是时候将您的新知识付诸实践了。为了让你能够完成剩下的章节,你的网站需要一些内容,所以在这一部分我给你设置了一个练习。

Exercise: Creating your site content

这个练习的目的是让你使用前两章中的所有插件,不仅是为了学习如何使用插件来创建真实的内容,还因为我们需要网站中的一些内容,这样我们就可以完成书中的剩余章节。

我已经提供了完整的示例网站作为本书源代码的一部分;但是,强烈建议您仅使用 if 作为参考,因为您将通过自己创建页面学到最多的东西。

在本练习中,我们将创建商业网站上最常见的三个页面:

  • 主页
  • “关于我们”页面
  • 联系页面

我们还将创建两个页面,稍后将成为博客帖子。我们现在要创建它们,这样当我们在下一章创建边菜单时,你就有东西可以在你的网站上显示了。

阶段 1:创建主页

Add a new page to your site and call it Home.   Switch to structure view and add an Image plugin to the content placeholder. Upload an image of your choice. For a challenge, you might want to try a Folder plugin instead and create an image slider to show several banner images, just like many popular websites.   Add a Text plugin to the page and enter a couple of introductory paragraphs.   Add a Multi Columns plugin with two columns set to 50%.   In the first column, add a Style plugin and then a Teaser plugin. Add some styles to format the teaser description. In the second column add another Text plugin and some text.   Add a final Text plugin and some closing text for the page.

保存并发布页面。我在图 8-10 中包含了一个主页样本。请注意,您的页面不必看起来完全像这样;重要的是练习使用插件。

A978-1-4842-1669-9_8_Fig10_HTML.jpg

图 8-10。

A sample home page

阶段 2:创建“关于我们”页面

Add a new page to your site and call it About.   Insert a single Text plugin and then insert all the content into the Text plugin. I suggest you add another image and a video and maybe a table—I’ll leave the details up to your imagination.

保存并发布页面。图 8-11 显示了这个页面可能的样子。

A978-1-4842-1669-9_8_Fig11_HTML.jpg

图 8-11。

A sample about page

阶段 3:创建联系人页面

Add a new page to your site and call it Contact   Add a Form plugin to the content placeholder.   At a minimum, your form should contain:

  • 文本字段类型的名称字段
  • 电子邮件类型的电子邮件字段
  • textarea 类型的消息字段

如果您想创建一个更高级的表单,您可以添加单选按钮或组合框来询问站点访问者他们第一次在哪里听说您的公司,并添加一个复选框来给访问者发送表单的机会。

保存并发布页面。图 8-12 展示了你的联系方式。如您所见,它非常简单,格式也很简单。作为进一步的练习,添加一个样式插件,并对表单应用一些样式,使其看起来更专业。请记住,您必须将表单插件拖到结构编辑器的样式插件中,以便将新样式应用到表单中。

A978-1-4842-1669-9_8_Fig12_HTML.jpg

图 8-12。

A sample contact page

阶段 4:创建博客文章

使用部分或全部插件,创建另外两个名为“blogpost1”和“blogpost2”的页面然后选择页面➤隐藏在导航中,使这些页面不显示在顶部菜单中,并发布每个页面。我们将在下一章把这些页面链接到侧边菜单,稍后,一旦你学会了如何扩展页面模型,我们将创建一个名为“博客”的页面类别,以便在我们的侧边菜单和最新的文章页面上显示它们和任何后续的博客文章。

这就是目前的内容创作。接下来,我们将探讨如何管理 django CMS 网站。

django CMS 管理局

django CMS 管理界面通过根菜单(图 8-1 )选择 example.com➤管理进入。默认的管理仪表板如图 8-13 所示。根据您安装的第三方插件,您的管理仪表板可能会有所不同。

A978-1-4842-1669-9_8_Fig13_HTML.jpg

图 8-13。

Default administration dashboard (shown maximized)

如果您以前使用过 Django,您应该对此很熟悉:显示了标准的 Django 身份验证和授权以及站点面板,以及一个用于 django CMS 功能的自定义面板。在管理界面中执行的三个最常见的管理任务是:

Adding, editing and deleting pages   Changing user permission settings   Modifying user and group authentication and authorization settings   Tip

如果你想把你的根菜单标题从example.com改成类似于My Blog的标题,去站点,选择example.com链接,把显示名称改成一个新标题。当您刷新页面时,工具栏根将从 example.com 更改为您的新标题。

页面管理

django CMS 页面管理界面如图 8-14 所示。可从 django CMS ➤页面下的管理仪表板或通过工具栏根(example.com ) ➤页面访问。图 8-14 显示了在你完成之前的练习后,你的页面管理界面会是什么样子。如果您已经跳到前面,页面列表将是空白的。

A978-1-4842-1669-9_8_Fig14_HTML.jpg

图 8-14。

django CMS page administration

可以从页面管理界面执行许多页面管理功能:

  • 通过右上角的按钮添加新页面和恢复删除的页面。

  • Reorder pages in the menu hierarchy by selecting the drag handle ( ) and dragging the page to the desired location.

    A978-1-4842-1669-9_8_Figa_HTML.jpg

    ) and dragging the page to the desired location.

  • The toolbar on the right of the page listing provides some handy page management tools. Table 8-1 details each of the available tools.

    表 8-1。

    Page Administration Page Tools

    | 工具 | 功能 | | --- | --- | | ![A978-1-4842-1669-9_8_Figb_HTML.jpg](https://img-blog.csdnimg.cn/img_convert/72a6ad5da1281b50a4b2c10a91bde47a.jpeg) | 根图标。如果页面是根页面,则显示。 | | ![A978-1-4842-1669-9_8_Figc_HTML.jpg](https://img-blog.csdnimg.cn/img_convert/dcdc6205dd4793bbbf31b51a3aa071ee.jpeg) | 查看页面。选择以使此页面成为当前页面。 | | ![A978-1-4842-1669-9_8_Figd_HTML.jpg](https://img-blog.csdnimg.cn/img_convert/5c7a7715467e1180688fb888254a64bb.jpeg) | 已发布图标。如果页面已发布,则为绿色;如果页面有未发布的更改,则为蓝色;如果页面未发布,则为灰色。可以通过选择图标进行切换。 | | ![A978-1-4842-1669-9_8_Fige_HTML.jpg](https://img-blog.csdnimg.cn/img_convert/9b2d584105c930d559f623ac1c5a4765.jpeg) | 在菜单图标中。已检查页面是否在顶部导航菜单中。通过选择图标可以直接切换该设置。 | | ![A978-1-4842-1669-9_8_Figf_HTML.jpg](https://img-blog.csdnimg.cn/img_convert/597e6779739e568e4f719edbdc4f21ed.jpeg) | 编辑页面属性。编辑页面设置。您也可以按住 Shift 键选择以访问高级设置。请注意,您不能从管理员那里编辑页面内容或结构,只能编辑设置。 | | ![A978-1-4842-1669-9_8_Figg_HTML.jpg](https://img-blog.csdnimg.cn/img_convert/4e069de49de122924efc22de41bb6b70.jpeg) | Copy page. When it is selected, the insert inside (![A978-1-4842-1669-9_8_Figh_HTML.jpg](https://img-blog.csdnimg.cn/img_convert/ce487a89848ccf5a082e138dc2a25897.jpeg)) icon will appear next to each page in your page list. Select the page you want to insert the page under. If you want to copy the page to the root level, first insert and then use the drag handle (![A978-1-4842-1669-9_8_Figa_HTML.jpg](https://i-blog.csdnimg.cn/blog_migrate/bf688ea9cc4de301c67187bd37325d16.jpeg)) to move the page to the desired position in the menu. | | ![A978-1-4842-1669-9_8_Figi_HTML.jpg](https://img-blog.csdnimg.cn/img_convert/2ae7106fb0956c3ca1832ea8a0c70b25.jpeg) | 将子页面添加到当前页面。 | | ![A978-1-4842-1669-9_8_Figj_HTML.jpg](https://img-blog.csdnimg.cn/img_convert/772de5766f0f2f122b0a9416980892a1.jpeg) | Cut page. When it is selected, the insert inside (![A978-1-4842-1669-9_8_Figb_HTML.jpg](https://img-blog.csdnimg.cn/img_convert/72a6ad5da1281b50a4b2c10a91bde47a.jpeg)) icon will appear next to each page in your page list; similar to the copy function. Select the page you want to insert the page under. If you want to insert the page at root level, it’s better to use the drag handle (![A978-1-4842-1669-9_8_Figa_HTML.jpg](https://i-blog.csdnimg.cn/blog_migrate/bf688ea9cc4de301c67187bd37325d16.jpeg)) to move the page to the desired position in the menu, rather than cut and reinsert. | | ![A978-1-4842-1669-9_8_Figk_HTML.jpg](https://img-blog.csdnimg.cn/img_convert/82448e7e8b94f730feccf5c0cf679414.jpeg) | 删除该页面。可以通过选择右上角的“恢复删除的页面”按钮来恢复。 | | ![A978-1-4842-1669-9_8_Figl_HTML.jpg](https://img-blog.csdnimg.cn/img_convert/540a3a0fbb9044a1332e648d6a939a01.jpeg) | Page information iconn Hover for basic page information. Example:![A978-1-4842-1669-9_8_Figm_HTML.jpg](https://img-blog.csdnimg.cn/img_convert/339af0a6db552c3086671aea5f1743b9.jpeg) |

用户管理

django CMS 用户管理如图 8-15 所示。可以从 django CMS ➤用户下的管理仪表板访问它,也可以通过工具栏 root(example.com)➤用户访问它。

A978-1-4842-1669-9_8_Fig15_HTML.jpg

图 8-15。

The User admin interface

django CMS 提供了许多简单明了的工具来管理用户:

  • 更改用户的用户名、密码、电子邮件以及名字和姓氏。
  • 将用户标记为活动或非活动。
  • 修改、添加和删除用户权限和组(请参见下一节)。
  • 检查用户的历史记录、注册日期和上次登录日期。

要修改用户信息,请选择他们的用户名,编辑窗口将会打开。

授权和用户权限

在我们继续创建和修改用户权限之前,我们需要理解它们所基于的底层身份验证模型:用户模型和分配权限。

用户模型

django CMS 权限系统建立在 django 的用户认证系统之上,增加了一些特殊的权限来简化 CMS 的管理。

Django 实现了基于用户的认证模型,最基本的元素是用户对象。

用户对象获得三种基本权限:

The ability to add an object   The ability to change an object   The ability to delete an object

Django 自动为您的INSTALLED_APPS中定义的每个 Django 模型创建所有这三种权限。要授予用户在 django CMS 中添加、更改或删除任何对象的权限,您需要添加权限。

要了解如何操作,请转到用户管理仪表板,选择一个用户名来编辑该用户。向下滚动页面到权限面板;我们要检查的字段是员工状态和超级用户状态复选框以及组和用户权限水平过滤器。

对于只有一个或两个管理员的简单站点,每个人都有对站点的完全访问权可能是可以的。在这种情况下,您只需要确保为每个用户检查职员状态和超级用户状态,不需要再设置任何权限;每个用户将有充分的访问该网站。

另一方面,如果你想控制对网站的访问,你需要设置权限。那么首先,我们来学习如何在 Django 中设置用户权限。如果您查看用户权限过滤器(图 8-16 ,您会看到左侧有一个权限列表,可以为每个对象选择权限。

A978-1-4842-1669-9_8_Fig16_HTML.jpg

图 8-16。

Setting user permissions

列表中有几十种权限;但是,它们都遵循相同的格式:<app> | <model> | <permission>,每个模型有三个权限,允许您分配添加、更改和/或删除权限。所有与 django CMS 核心相关的权限都列在 CMS 应用(cms| …)下,所有默认的插件应用权限都以djangocms_开头(例如,djangocms_column表示多列插件)。如果你遵循了书中的其他例子,你也会看到filereasythumbnails插件的权限。

Django 组(图 8-17 )是一种创建类别的通用方法,可以将组权限应用于个人用户。分配给某个组的用户将继承分配给该组的所有权限。用户可以属于多个组。

A978-1-4842-1669-9_8_Fig17_HTML.jpg

图 8-17。

Django user groups

对于 CMS 来说,组提供了一个明显的优势,即能够定义一组权限(对于一个作者或一个编辑),然后可以应用到单个用户。在这个阶段,您可能很想这样做:创建作者和编辑组,并分别分配每个权限,但是 django CMS 附带了对 django 默认权限的扩展,使这变得容易多了。

django CMS 中的权限

django CMS 扩展了 django 的用户模型,并为在 django CMS 页面上设置权限提供了两个新模型:

  • 用户组(第页)
  • 用户(第页)

用户(页面)模型与 Django 模型几乎完全相同,所以我们在这里不再赘述,但是用户组(页面)模型(图 8-18 )增加了一些有用的功能,使得为常见的 CMS 任务设置权限变得非常简单。

A978-1-4842-1669-9_8_Fig18_HTML.jpg

图 8-18。

Adding a user group

例如,让我们创建一个名为 Editor 的新组。为新组添加以下权限:

  • 页面权限:添加、更改和删除
  • 用户和组权限:全部未选中
  • 页面权限管理:全部未选中

这些权限反映了您对页面编辑器的期望:他们可以添加、更改和删除页面,但不能添加、更改或删除其他用户的权限。

如果您导航回管理仪表板并打开身份验证和授权➤组➤编辑器,您应该会看到类似图 8-19 的内容。

A978-1-4842-1669-9_8_Fig19_HTML.jpg

图 8-19。

Permissions have been added automatically to a group

您可以在这里看到,django CMS 根据您在创建用户组时选择的权限设置添加了许多权限。在练习中,创建一个新用户并将他们分配到编辑组。保存新用户时,请确保选中了员工状态,并且未选中超级用户状态。如果您注销并以新用户的身份重新登录,您会马上注意到一些事情:工具栏中的页面菜单不见了,您不能编辑任何东西!

什么给的?

django CMS 和 django 一样,有一个自底向上的权限系统,通常被称为“默认拒绝”。要向用户提供完整的权限集,您需要添加权限来增加访问权限,而不是取消权限来限制访问权限。这提供了一个更加健壮和安全的身份验证模型。

当您创建您的用户和编辑组时,您的新组仅被授予页面编辑权限,但没有编辑页面所需的插件的实际访问权限。也没有为您提供对页面菜单的工具栏访问,因为这需要全局页面访问。

你可能会觉得不自动添加像文本插件这样的基本插件很奇怪,因为它们是编辑任何东西所必需的。我同意,但是 django CMS 遵循 Python“显式优于隐式”的哲学,让您来设置权限。

一家公司的网站就是一个很好的例子,可以证明这是一件好事。因为站点管理员能够单独限制插件,所以他们可以允许用户向公司网站添加和编辑文本,但是可以通过不提供使用这些插件的权限来限制用户插入链接和视频。是的,他们可以通过编写普通的 HTML 来绕过这一点,但是这种方法对于潜在的安全问题(和潜在的不适当的内容)是非常有效的。)是由在文字处理器之外经验有限的用户添加的。

因此,为了给我们的新用户适当的权限来编辑页面,我们需要添加更多的权限。以新用户身份注销,然后以管理员身份重新登录。

Tip

权限设置可能不正确,因此当您以其他用户身份登录时,工具栏会消失。这是一个问题,因为没有工具栏你就不能再次退出。如果您发现自己处于这种情况,仍然可以通过将/admin附加到您的 URL 来访问 Django 管理界面。以管理员身份重新登录,您将再次拥有完全访问权限来修复任何被破坏的权限。

首先,从管理仪表板中,选择“页面全局权限”,然后选择顶部的“添加页面全局权限”按钮。您需要将组下拉列表设置为您的编辑组,并选中除“查看受限”和“保存记录”之外的所有复选框。

完成此操作后,返回“身份验证和授权➤组➤编辑器”(从“管理控制面板”),选择以下所有权限(添加、更改、删除):

  • cms |别名插件模型
  • 厘米|内容管理系统插件
  • cms |页面
  • cms |占位符
  • cms |静态占位符
  • cms | title |可以添加标题
  • cmsplugin_filer_ *
  • djangocms_*
  • 简易缩略图
  • 文件编档员

将这些权限添加到编辑组并保存后,您的新用户应该能够执行与您的管理员相同的所有页面编辑功能,但不能访问网站的任何管理功能。

摘要

本章到此为止。现在,您应该有几个页面和文章添加到您的网站,并完全了解如何管理用户和组织内容。

在下一章中,我们将通过侧边栏菜单向用户展示你全新的博客页面,同时查看网站的其他导航工具:面包屑和网站地图。

九、菜单和导航

在这个阶段,我们完整的博客网站开始成型:我们已经建立了自己的模板,了解了所有 django CMS 插件的工作方式,并使用它们为我们的网站创建了一些内容。然而,我们还有一段路要走,因为我们的网站导航仍然非常基础。

在这一章中,我们将添加一些常见的导航元素,从一个包含博客文章链接的自定义菜单开始。

在这一章的后面,我们将添加社交媒体按钮和一个网站地图来帮助你的第二重要的网站访问者:搜索引擎。

这一章也是我们第一次深入编写一些 Django 代码,所以如果你还不太了解 Django 和 Python,现在是时候更新这些技能了。在第十一章中有一些关于 Django 和 Python 的链接。

自定义菜单

django CMS 菜单系统既灵活又可扩展。到目前为止,我们只看到了 django CMS 如何自动将页面添加到我们的主菜单中,但这并不是其功能的极限——使用 django CMS,您可以执行以下所有操作:

  • 用自定义条目静态扩展现有菜单。
  • 创建链接到您的应用和插件的自定义菜单。
  • 将自定义菜单附加到页面。
  • 创建将修改整个菜单树的导航修饰符(例如,应用特殊格式)。

我们将在下一章探索更高级的功能,但是第一次做的时候会有点复杂,所以在这一章,我将通过展示如何将一个定制的博客菜单附加到我们的主菜单来介绍定制菜单。

Note

本章假设您已经根据第八章中的练习创建了博客页面。如果您还没有这样做,请确保您发布了至少两个新页面,并选择页面➤在导航中隐藏以在根菜单中隐藏它们。

首先,我们需要创建一个新页面。将新页面命名为 Blog,并选择带有侧边栏模板的博客页面。我们将把自定义菜单附加到此页面。

创建自定义菜单

有两个选项可用于自定义菜单:您可以静态扩展现有的主菜单,或者将自定义菜单附加到主菜单中的特定页面。

这两个选项之间的唯一区别是在构建菜单时扩展了哪个 django CMS 类:

  • 为了静态扩展主菜单,您的自定义菜单类必须扩展menus.base.Menu
  • 要将自定义菜单附加到现有页面,您的自定义菜单类必须扩展cms.menu_bases.CMSAttachMenu

这用一个例子就容易理解多了。在你的应用目录(/myblog/)中创建一个名为menu.py的新文件,并输入清单 9-1 中所示的代码。

Listing 9-1. Custom Menu Attached to Root

#menu.py

from menus.base import Menu, NavigationNode

from menus.menu_pool import menu_pool

from django.utils.translation import ugettext_lazy as _

class BlogMenu(Menu):

def get_nodes(self, request):

nodes = []

n1 = NavigationNode(_('Test1'), "/newpost1/", 1)

n2 = NavigationNode(_('Test2'), "/newpost2/", 2)

n3 = NavigationNode(_('Test3'), "/newpost3/", 3)

nodes.append(n1)

nodes.append(n2)

nodes.append(n3)

return nodes

menu_pool.register_menu(BlogMenu)

让我们来看看这段代码:

  • 在第 1 行,我们从menus.base导入了类MenuNavigationNode,这意味着菜单将被附加到根菜单(主菜单)。
  • 然后我们创建我们的BlogMenu类,它扩展了Menu类。
  • get_nodes函数通过追加由NavigationNode类创建的菜单节点列表来构建菜单。
  • 最后,我们向 django CMS 注册新的定制菜单,将其添加到菜单池中。

The NavigationNode class

我们新的定制菜单类的核心是NavigationNode类,它构建了我们的菜单项。get_nodes函数向您的应用返回一个NavigationNode实例的列表,这样它们就可以呈现在菜单中。NavigationNode采用以下参数:

  • Title。菜单链接中的锚文本。
  • url。菜单项链接到的页面(内部或外部)的 URL。
  • Id。此菜单项的唯一 ID。
  • parent_id。可选;默认= None。如果这是子节点,则为父节点的 ID。
  • parent_namespace。可选;默认= None。这是一个高级设置;更多信息请参见 django CMS 文档。
  • Attr。可选;默认= None。这是一个高级设置;更多信息请参见 django CMS 文档。
  • Visible。可选;默认= True。设置为False隐藏该菜单项。

保存您的menu.py文件并重启开发服务器。当你刷新你的浏览器时,你应该看到来自你的PostMenu自定义菜单的项目被附加到菜单的末尾(图 9-1 )。

A978-1-4842-1669-9_9_Fig1_HTML.jpg

图 9-1。

Custom menu appended to the main menu

以这种方式扩展根菜单的一个实际应用是添加链接到外部应用的菜单项(我们将在第十章中这样做)以及其他网站。

为了创建一个可以附加到页面上的菜单,我们需要对我们的文件做一些修改(清单 9-2 )。我用粗体突出显示了这些变化。

Listing 9-2. Custom Menu Attached to Page

from menus.base import NavigationNode #Menu has been removed

from menus.menu_pool import menu_pool

from django.utils.translation import ugettext_lazy as _

from cms.menu_bases import CMSAttachMenu

class PostMenu(``CMSAttachMenu

#Menu Name (shows in dropdown)

name = _("post menu")

def get_nodes(self, request):

nodes = []

n1 = NavigationNode(_('Test1'), "/newpost1/", 1)

n2 = NavigationNode(_('Test2'), "/newpost2/", 2)

n3 = NavigationNode(_('Test3'), "/newpost3/", 3)

nodes.append(n1)

nodes.append(n2)

nodes.append(n3)

return nodes

menu_pool.register_menu(PostMenu)

一旦您保存了menu.py,您需要将自定义菜单附加到页面上。我们将把它附加到您的新博客页面,所以在菜单上选择它,然后转到 django CMS 工具栏,选择页面➤高级设置➤附加➤邮报。您可能需要在高级设置框中向下滚动一点才能找到附加的菜单设置。保存您的更改。你的主菜单现在应该如图 9-2 所示。

A978-1-4842-1669-9_9_Fig2_HTML.jpg

图 9-2。

Custom menu attached to a page

虽然我们新的定制菜单令人印象深刻,但它并没有多大用处;菜单链接只是指向不存在的页面。如果链接指向我们的博客文章,它就会变得有用。我们这样做的方式非常简单;我们只需要用实际博客文章的标题和 URL 替换示例值titleurl

这很容易做到,但首先我们必须多理解 django CMS PageTitle模型。简而言之,django CMS 不会在一个模型中存储页面的所有信息;主要是它有一个Title模型,存储关于页面不同版本的信息(例如,语言版本、元数据和草稿版本)。Page模型存储与页面相关的信息,如发布日期、安全设置和页面模板。

TitlePage模型中的字段比我们在这里讨论的时间要多得多;我鼓励您浏览 django CMS 文档,以全面了解这些模型,因为它们是 django CMS 中更高级编程的核心。出于自定义菜单的目的,我们只对博客文章的标题及其 URL 感兴趣。容易吗?

不完全是。有几个需要注意的地方,理解发生了什么的最好方法是让我们稍微偏离一下主题,用 Python 交互式提示来探索一下PageTitle模型。打开一个命令窗口,确保您已经启动了虚拟环境。您的命令提示符应该如下所示:

(myBlog) c:\Users\<your username>\MyBlogProject>

在项目目录中,输入以下内容:

python manage.py shell

您应该会看到一些启动消息,后面是 Python 交互提示(>>>)。输入下面的代码,按回车键(不要输入三个点;Python 自动插入它们):

>>> from cms.models import Title

>>> for t in Title.objects.all():

...     print(t.title)

这是直接的 Django (Python)代码。我们循环访问数据库中的所有Title对象,并打印每个对象的标题字段。在我的机器上,该命令输出以下内容:

...

Home

Home

About Us

Contact

BlogPost1

BlogPost2

Blog

显然这是不好的——遍历标题会给你数据库中的所有页面,而不仅仅是博客文章,所以我们需要把它们分开。你还会注意到Home是重复的。这是因为 django CMS 还为任何有草稿版本的页面保留了一个标题条目,所以我们也必须排除任何页面的草稿版本。

找出一个页面是否是草稿很容易;django CMS Page模型包含一个名为publisher_is_draft的布尔(真/假)属性。因为我们在主菜单中隐藏了博客文章,所以我们将使用另一个名为in_navigation的布尔页面属性从页面列表中提取博客页面。

在你抱怨之前,是的,我同意,in_navigation不是识别博客文章的好方法,因为任何隐藏在主菜单中的页面都会出现在博客菜单中。因为我们要到下一章才会学习如何扩展PageTitle模型(添加一个类别字段),所以把这看作一个说明性的例子,而不是一个实用的例子!

让我们用交互式控制台对此进行测试:

>>> from cms.models import Title

>>> for t in Title.objects.all():

...     print(t.title, t.page.in_navigation,t.page.publisher_is_draft)

...

Home True True

Home True False

About Us True True

Contact True True

BlogPost1 False True

BlogPost2 False True

Blog True True

从这里,我们可以看到第一个主页确实是一个草稿,这两篇博文是唯一不在主导航菜单中的页面(in_navigation=False)。注意,我们在这里没有加载Page模型;由于pageTitle模型的外键,我们可以从带点(.)运算符:Title.page.<attribute>

所以现在我们要把新发现的知识转化成一些有用的代码。我们仍然需要找到博客页面的 URL 我们通过path属性来实现:

>>> from cms.models import Title

>>> for t in Title.objects.all():

...     if t.page.in_navigation==False and t.page.publisher_is_draft==False:

...             print(t.title, t.path)

...

BlogPost1 blogpost1

BlogPost2 blogpost2

>>>

现在你已经理解了这一切是如何工作的,新的menu.py代码(列表 9-3 )应该很容易理解(新代码以粗体显示)。

Listing 9-3. The menu.py File with Modifications

#menu.py

from menus.base import NavigationNode #Menu has been removed

from menus.menu_pool import menu_pool

from django.utils.translation import ugettext_lazy as _

from cms.menu_bases import CMSAttachMenu

from cms.models import Title

class PostMenu(CMSAttachMenu):

#Menu Name (shows in dropdown)

name = _("post menu")

def get_nodes(self, request):

nodes = []

for t in Title.objects.all():

如果 t.page.in_navigation==False 并且A978-1-4842-1669-9_9_Figa_HTML.jpg

t.page.publisher_is_draft==False:

n = NavigationNode(_(t.title), "/" + t.path + "/", 1)

nodes.append(n)

return nodes

menu_pool.register_menu(PostMenu)

刷新您的浏览器(您可能需要重启开发服务器),您的博客定制菜单现在应该如图 9-3 所示。

A978-1-4842-1669-9_9_Fig3_HTML.jpg

图 9-3。

Complete custom blog menu

正如我前面所说,这只是一个例子,说明在 django CMS 中构建自定义菜单是多么容易。我不建议将它作为显示博客文章的实用解决方案;对于初学者来说,一旦你有了更多的博客条目,这将创建一个笨拙的菜单。

在下一章中,一旦你学会了如何扩展TitlePage模型,你将能够构建更加实用的定制菜单。例如,一旦您为每个页面添加了一个类别字段,该菜单就可以链接到特定类别中的所有页面,并使用 Blog Roll 模板显示最新的五篇文章。

面包屑

术语面包屑或面包屑痕迹是指网站上的一行二级导航,显示用户在页面结构中的当前位置。面包屑通常显示在网页正文的上方。

为了给网站添加面包屑,django CMS 提供了一个方便的模板标签show_breadcrumb。它有三个可选参数:

start_level. Where to start in the navigation hierarchy. Default = 0 (root).   template. The breadcrumb template to use. For portability, you should always create a custom template for your app. By convention, it’s a file named breadcrumb.html, but you can name the template file anything you wish. We need to create this file for the breadcrumbs to work. In Listing 9-5 you’ll see a simple breadcrumb.html file.   only_visible. Only show pages that are visible in the menu navigation. Default = 1 (true); set to 0 to show all pages.

要在您的应用中呈现面包屑轨迹,您需要使用以下格式将模板标签添加到页面模板:

{% Show_breadcrumb start_level, template, only_visible %}

所以让我们开始吧。用清单 9-4 中所示的代码修改您的base.html文件。我已经包括了一些现有的代码,所以你可以看到新代码放在哪里。

Listing 9-4. Modifications to base.html for Breadcrumbs

#modify base.html

. . .

<div class="blog-header">

<h1 class="blog-title">Not Just Another Blog</h1>

<p class="lead blog-description">My awesome blog built with django CMS.</p>

</div>

<div class="breadcrumb">

{% show_breadcrumb 0 "breadcrumb.html" %}

</div>

{% block content %}{% endblock content %}

</div>

. . .

这里的代码很简单;我们从根开始显示面包屑,并且我们使用了breadcrumb.html定制模板。现在我们需要创建模板本身(清单 9-5 )。将文件breadcrumb.html保存到/myblog/templates

还要注意,我已经将类breadcrumb应用于 breadcrumb 模板标签周围的 div 是一个引导类,它会自动将一些漂亮的格式应用到我们的面包屑轨迹中。

Listing 9-5. Our breadcrumb.html Template File

#breadcrumb.html

{% for ancestor in ancestors %}

{% if not forloop.last %}

<a href="{{ ancestor.get_absolute_url }}"> A978-1-4842-1669-9_9_Figa_HTML.jpg

{{ ancestor.get_menu_title }}</a>

<span class="separator"> | </span>

{% else %}

<span class="active">{{ ancestor.get_menu_title }}</span>

{% endif %}

{% endfor %}

浏览清单 9-5 ,我们可以看到 Django 代码循环遍历导航层次结构并显示每个祖先,用管道字符(“|”)分隔。在最后一次循环中,if语句失败,执行else语句,将当前页面附加到 breadcrumb trail。假设你得到了所有正确的代码,你的页面现在应该看起来如图 9-4 所示。

A978-1-4842-1669-9_9_Fig4_HTML.jpg

图 9-4。

Our pages with the breadcrumb trail added

社交按钮

像脸书和推特这样的社交媒体网站非常受欢迎,可以分享各种内容,包括最喜欢的博客文章;如此受欢迎,以至于几乎所有受欢迎的博客网站上都有喜欢和分享社交媒体按钮。

django CMS 有几个第三方插件来实现与社交媒体平台的交互,包括喜欢和分享按钮;然而,在这一节,我将教你如何将简单的社交媒体功能直接嵌入到你的网站中。这是一项需要学习的有用技能,因为它可以应用于大量需要嵌入 HTML 片段和加载 JavaScript 库的应用、其他社交媒体网站和工具(如 Google Analytics)。

django CMS 让嵌入社交媒体功能变得非常简单;我们将使用一个静态占位符,一些来自脸书和 Twitter 的嵌入代码,以及一些 JavaScript 库的组合。一旦我们完成,你的博客文章底部会有分享按钮,如图 9-5 。

A978-1-4842-1669-9_9_Fig5_HTML.jpg

图 9-5。

Social media Share buttons added to blog pages

如果您还记得第五章中的,我们已经为blogpage.html添加了以下静态占位符:

{% static_placeholder "social" %}

从右侧导航菜单中选择一篇博客文章,并将其模板设置为带侧边栏的博客页面(带侧边栏的页面➤模板➤博客页面)。如果您切换到结构视图,您会注意到您已经切换到博客模板,该模板添加了社交按钮占位符(图 9-6 )。

A978-1-4842-1669-9_9_Fig6_HTML.jpg

图 9-6。

Blog template with additional placeholders

向社交占位符添加一个文本插件,并输入清单 9-6 中的文本。

Caution

在输入文本之前,将文本插件切换到源模式;否则是不行的。

Listing 9-6. Code to Embed Social Buttons

<div class="fb-share-button"

data-layout="button_count"

style="float: left;">

</div>

<div style="float: left;"><a class="twitter-share-button"

href="https://twitter.com/intent/tweet?

text=check%20this%20out%3A%20 ">Tweet</a>

</div>

第一个div嵌入了脸书分享按钮,第二个div嵌入了推特分享按钮。

接下来,我们需要添加脸书和 Twitter 的 JavaScript 库。为此,我们必须修改两个模板文件:base.htmlblogpage.html

base.html中,我们需要为脸书添加一个锚点,以便能够将元素附加到 HTML DOM 中。将下面的代码放在 body 标签的正下方:

<div id="fb-root"></div>

然后在底部,就在{% render_block "js" %}模板标签的上方,添加另一个模板标签:

{% block js %}{% endblock %}

因为我们将把 JavaScript 添加到扩展模板中,所以这个新块是必需的,以便django-sekizai知道在我们的扩展模板中添加额外的脚本。继续之前保存base.html

现在我们需要修改blogpage.html。由于这是一个相当大的修改,我复制了清单 9-7 中的文件,并用粗体显示了修改。

Listing 9-7. Blogpage.html with Modifications

#blogpage.html

{% extends "page.html" %}

{% load cms_tags %}

{% load sekizai_tags %}

{% block title %}{% page_attribute "page_title" %}{% endblock title %}

{% block js %}

{% addtoblock "js" %}

<script>

window.twttr = (function(d, s, id) {

var js, fjs = d.getElementsByTagName(s)[0],

t = window.twttr || {};

if (d.getElementById(id)) return t;

js = d.createElement(s);

js.id = id;

js.src = "https://platform.twitter.com/widgets.js

fjs.parentNode.insertBefore(js, fjs);

t._e = [];

t.ready = function(f) {

t._e.push(f);

};

return t;

}(document, "script", "twitter-wjs"));

</script>

{% endaddtoblock %}

{% addtoblock "js" %}

<script>(function(d, s, id) {

var js, fjs = d.getElementsByTagName(s)[0];

if (d.getElementById(id)) return;

js = d.createElement(s); js.id = id;

js.src = "//connect.facebook.net/en_US/sdk.js#xfbml=1``&

fjs.parentNode.insertBefore(js, fjs);

}(document, 'script', 'facebook-jssdk'));

</script>

{% endaddtoblock %}

{% endblock %}

{% block page-inner %}

<div class="blog-post">

<h2 class="blog-post-title">Sample blog post</h2>

<p class="blog-post-meta">October 1, 2015 by <a href="#">Nige</a></p>

{% placeholder "content" %}

{% static_placeholder "social" %}

{% static_placeholder "navbuttons" %}

</div>

{% endblock page-inner %}

Tip

Twitter 的最新脚本可以在 https://dev.twitter.com/web/javascript/loading 找到,脸书的最新脚本可以在 https://developers.facebook.com/docs/plugins/share-button 找到。

从清单中可以看到,我们使用了django-sekizai {% addtoblock %}标签来插入来自 Twitter 和脸书的 JavaScript 库。还要注意,我只为每个{% addtoblock %}标签加载了一个脚本。这是使用django-sekizai的最佳实践,也是django-sekizai能够防止重复 JavaScript 库所必需的。

如果你保存blogpage.html并刷新你的网站,你会在每篇文章的末尾看到脸书和推特分享按钮,如图 9-5 所示。

正如我在本节开始时所说的,这种方法不仅对嵌入社交媒体工具有用;它可以用于任何需要在页面中添加 HTML 代码片段和加载 JavaScript 的工具或应用。

网站地图

虽然关于网站地图是否有用还有很多争论,但是网站开发者创建网站地图的主要原因——谷歌——表明这是一个好主意,特别是对于新网站。幸运的是,django CMS 使得添加一个站点地图变得如此简单,以至于我的建议总是相同的:考虑到它花费的精力如此之少,添加一个站点地图。

网站地图是一个 XML 文件,搜索引擎用它来索引你的网站。你可以使用谷歌网站管理员工具等工具向搜索引擎提供你的sitemap.xml文件的链接。

Django 内置了一个 sitemap 框架:django.contrib.sitemaps。django CMS 用一个名为CMSSitemap的新类扩展了这个框架,该类负责将标题、出版物信息和位置信息编入站点地图,因此您不必创建自己的 django 站点地图类。

向您的站点添加站点地图就像以下步骤一样简单:

Add django.contrib.sitemaps to your project’s INSTALLED_APPS setting (should be installed by default).   Add from cms.sitemaps import CMSSitemap to the top of your main urls.py.   Add url(r'^sitemap\.xml$', 'django.contrib.sitemaps.views.sitemap', {'sitemaps': {'cmspages': CMSSitemap}}) to your urlpatterns.

清单 9-8 显示了urls.py的一个部分,其中包含相关的修改(变化以粗体显示)。

Listing 9-8. urls.py Sitemap Modifications

#urls.py (partial)

. . .

from django.contrib import admin

from django.conf import settings

from cms.sitemaps import CMSSitemap

admin.autodiscover()

urlpatterns = i18n_patterns('',

url(r'^admin/', include(admin.site.urls)),  # NOQA

url(r'^sitemap\.xml$', 'django.contrib.sitemaps.views.sitemap',

{'sitemaps': {'cmspages': CMSSitemap}}),

url(r'^select2/', include('django_select2.urls')),

url(r'^', include('cms.urls')),

url(r’^sitemap.xml$ ‘,’ django . contib . site maps . views . site map ',A978-1-4842-1669-9_9_Figa_HTML.jpg

{'sitemaps': {'cmspages': CMSSitemap}}),

)

. . .

如果你导航到 http://127.0.0.1:8000/en/sitemap.xml ,你应该会看到一个类似于图 9-7 的网站地图。

A978-1-4842-1669-9_9_Fig7_HTML.jpg

图 9-7。

Snapshot of your sitemap file

摘要

在这一章中,我们已经讨论了 django CMS 中菜单和导航的一些更高级的主题。我们已经了解了如何创建自定义菜单、扩展默认导航菜单、创建面包屑导航以及添加一些社交共享按钮。

在下一章,我们将更深入地研究定制 django CMS。我们将编写一些代码来扩展 django CMS,您将看到如何为它编写您自己的定制应用和插件。

十、扩展 django CMS

django CMS 是高度可扩展的;这部分归功于 Django 固有的可扩展性,部分归功于 django CMS 的开放和可插拔设计。这是 django CMS 最大的能力,也是它的核心。

因为这是一个很深很详细的主题,所以本章只能涵盖一些扩展 django CMS 的更重要的方法。对于那些想更深入了解的人,我鼓励你去探索 django CMS 文档,以及许多更详细讨论 django 和 django CMS 的在线论坛(参考资料见第十一章)。

首先,我将向您展示如何通过为您的 CMS 页面创建一个类别字段来扩展 django CMS 中的PageTitle模型。这个类别将在以后构建自定义菜单插件时使用。

然后,我们将探讨如何向您的网站添加任何类型的 Django 应用,无论是第三方应用还是您自己构建的应用。在这个练习中,我们将使用 Django 教程中的 Polls 应用,而不是从头开始构建自己的程序。然后,我将向您展示如何使用 django CMS apphook 将应用附加到您的网站上。

然后我们将看看 django CMS 的另一个可扩展部分——工具栏。我将向您介绍通过添加我们的投票应用来扩展工具栏,以便它可以从您的网站前端编辑。

最后,我将介绍自定义插件,并教你如何创建和实现你自己的自定义插件,用于你的应用,以及与其他 django CMS 用户共享。

扩展页面和标题模型

在前一章中,我使用了我们的博客页面来演示如何创建一个定制菜单,但是我注意到这不是一个健壮的例子,因为我们使用了in_navigation属性来标识博客文章。最好是一个类别属性,这样我们就可以通过类别来识别页面:一个页面类别用于网站上的静态页面,一个文章类别用于博客文章。

开箱即用,Title模型和Page模型都没有这样的属性。幸运的是,PageTitle模型都是可扩展的。扩展这些模型的能力是 django CMS 的强大特性之一。

扩展每个模型的过程是相同的,所以我在这里只向您展示如何扩展Page模型,但是您可以在清单中找到注释,在那里您可以更改代码来扩展Title模型。要向您的每个页面添加类别,我们需要完成四个步骤:

Create the models.   Register the models with Django admin.   Create a toolbar item.   Add a category to each page.

创建模型

首先,我们需要为自己构建几个模型(列表 10-1 )。将此文件另存为models.py到您的应用目录(/ myblog /)。

Listing 10-1. The Category and CategoryExtension Models

from django.db import models

from cms.extensions import PageExtension #TitleExtension

from cms.extensions.extension_pool import extension_pool

class Category(models.Model):

category = models.CharField(max_length=20)

class Meta:

verbose_name_plural = 'Categories'

def __str__(self):

return self.category

class CategoryExtension(PageExtension): #TitleExtension

category = models.ForeignKey(Category)

extension_pool.register(CategoryExtension)

逐句通过这段代码,请注意以下几点:

  • 我们正在从cms.extensions类中导入PageExtensionextension_pool
  • Category类是一个标准的 Django 模型。Meta类和__str__(self)函数确保模型在管理界面中显示人性化的文本。
  • 我们的CategoryExtension类扩展了Page模型。它有一个链接到我们类别列表的外键字段。
  • 最后,我们向扩展池注册我们的扩展类。
  • 要修改这段代码以扩展Title模型,我们所要做的就是用TitleExtension替换PageExtension的每个实例。

一旦我们创建了新的模型,我们需要将它们添加到我们的应用中。为此,只需运行以下语句:

python manage.py makemigrations

python manage.py migrate

向 Django 管理员注册模型

接下来,我们需要向管理界面注册我们的新模型,这样我们就可以编辑它们了。继续在你的应用目录中创建一个新的admin.py文件,并输入清单 10-2 中所示的代码。

Listing 10-2. Registering our Models With Django Admin

from django.contrib import admin

from cms.extensions import PageExtensionAdmin #TitleExtensionAdmin

from .models import Category, CategoryExtension

class CategoryAdmin(admin.ModelAdmin):

pass

class CategoryExtensionAdmin(PageExtensionAdmin): #TitleExtensionAdmin

pass

admin.site.register(Category, CategoryAdmin)

admin.site.register(CategoryExtension, CategoryExtensionAdmin)

和前面的清单一样,这是标准的 Django 代码。我们已经创建了两个类存根,并向 Django 管理应用注册了它们,这样我们就可以从后端编辑模型。一旦您重启了开发服务器,您应该有一个新的面板添加到您的管理界面(图 10-1 )。

A978-1-4842-1669-9_10_Fig1_HTML.jpg

图 10-1。

Categories model added to admin interface

在管理控制台中,继续添加页面和文章类别。完成后,你的类别列表应该如图 10-2 所示。

A978-1-4842-1669-9_10_Fig2_HTML.jpg

图 10-2。

Categories list

创建工具栏项目

您会注意到,我们的扩展字段没有出现在管理界面中。这是因为在默认的管理应用中不能直接编辑Page模型。要将扩展字段附加到页面上,我们需要创建一个工具栏项目。为此,我们需要在我们的应用目录中创建一个名为cms_toolbar.py(列表 10-3 )的文件。django CMS 将在启动时查找这个文件,如果它存在,将文件中的类加载到工具栏中。

Listing 10-3. cms_toolbar.py

from cms.toolbar_pool import toolbar_pool

from cms.extensions.toolbar import ExtensionToolbar

from django.utils.translation import ugettext_lazy as _

from .models import CategoryExtension

@toolbar_pool.register

class CategoryExtensionToolbar(ExtensionToolbar):

model = CategoryExtension

def populate(self):

current_page_menu = self._setup_extension_toolbar()

if current_page_menu:

page_extension, url = self.get_page_extension_admin()

if url:

current_page_menu.add_modal_item(_('Page Category'), A978-1-4842-1669-9_10_Figa_HTML.jpg

url=url, disabled=not self.toolbar.edit_mode)

逐句通过代码,请注意以下事项:

  • 我们用toolbar_pool.register装饰器注册工具栏类。
  • 我们让 django CMS 知道我们想要为工具栏项目使用CategoryExtension模型。
  • 为了将我们的模型添加到工具栏中,我们从ExtensionToolbar中调用_setup_extension_toolbar()函数。这为我们的工具栏项目做了所有的初始化和设置。如果失败,它返回False,所以如果你的扩展模型有问题,这个函数会通过不加载你的类而优雅地失败。

输入代码后,保存cms_toolbar.py文件并重启服务器。如果您输入的一切都正确,现在您的页面菜单上会有一个新选项(图 10-3 )。

A978-1-4842-1669-9_10_Fig3_HTML.jpg

图 10-3。

Page extended field added to toolbar

向您的页面添加类别

你现在可以给你的每个页面添加一个类别了(图 10-4 )。因为我们将在本章的下一节使用类别,所以继续将博客类别分配给你的每篇博客文章,将页面类别分配给其他三个页面。

A978-1-4842-1669-9_10_Fig4_HTML.jpg

图 10-4。

Adding a category to a page

应用和应用挂钩

通常,您会希望将 django CMS 扩展到核心功能之外,以扩展整个网站的功能。扩展网站的两种方式是添加或创建 Django 应用(Django apps)和添加或创建 django CMS 插件。

两者之间的根本区别在于,应用是一个独立的应用,附加到您的网站上,可以通过 URL 访问(或附加一个 apphook),而插件是一个放在页面占位符中的对象。

在这一部分,我们将学习应用和应用挂钩;我们将很快介绍插件。向 django CMS 添加应用的流程与向 django 添加应用的流程相同:

Add a new app folder with startapp (or copy an existing app into your project directory).   Link to the app from your urls.py file.

对于这一章,我们将使用 Django 教程中的 Polls 应用,而不是从头开始编写应用。要在项目中安装应用,请按照以下步骤操作:

Download the Polls app from https://github.com/big-nige/django-polls . (Select the Download .ZIP button on the right of the page.)   Extract the downloaded zip file to your computer.   Open the extracted folder and copy the polls directory to your project directory.   Add the Polls app to your settings.py (Listing 10-4)   Add the Polls app to your urls.py (Listing 10-5)   Run python manage.py migrate polls from your virtual environment command prompt.   Listing 10-4. Adding the Polls App to settings.py

INSTALLED_APPS = (

. . .

'polls',

)

Listing 10-5. Adding the Polls App URLs to urls.py

urlpatterns = i18n_patterns('',

. . .

url(r'^polls/', include('polls.urls', namespace='polls')),

url(r'^', include('cms.urls')),

. . .

)

完成这些步骤后,项目目录应该如下所示:

/MyBlogProject

. . .

/myBlog/

/polls/

. . .

如果您导航到您的管理仪表板(通过工具栏),您应该会看到一个为我们的投票应用添加的新面板(图 10-5 )。

A978-1-4842-1669-9_10_Fig5_HTML.jpg

图 10-5。

Polls app added to the admin interface

继续添加几个投票。完成后,您可以导航到 http://127.0.0.1:8000/polls/ 来查看您的投票应用的运行情况。

您会注意到这是一个没有格式的普通页面。这是因为您尚未将投票应用更改为使用您的网站模板。要更改这一点,请编辑myBlogProject\polls\templates\polls\base.html以匹配清单 10-6 。

Listing 10-6. The Modified Polls Base Template

{% extends 'page.html' %}

{% block content %}

{% block polls_content %}

{% endblock %}

{% endblock %}

当你刷新你的/polls/页面时,你的投票应用现在应该使用你的站点模板(图 10-6 )。

A978-1-4842-1669-9_10_Fig6_HTML.jpg

图 10-6。

Polls app modified to use site template

Apphooks

虽然将应用添加到 django CMS 项目非常简单,正如我们的示例投票应用所展示的那样,但它仍然没有集成到 django CMS 中,因此它可以通过站点菜单访问或从前端修改。

apphook 允许你将一个应用附加到一个空的 django CMS 页面上,这样就可以通过主菜单访问它。在本节中,您将学习如何创建 apphook。

从前端修改 Polls 应用需要一个工具栏扩展,我们将在接下来讨论。

为了收集和注册 apphooks,django CMS 在应用的根目录中查找一个名为cms_apps. py的文件。一个基本的cms_apps.py文件如清单 10-7 所示。现在,在您的\polls\目录中创建这个文件。

Caution

注意,模块名是cms_apps.py。在 django CMS 的以前版本中,该模块被命名为cms_app.py。如果您使用的是较旧的 Django 或 django CMS 应用,您需要将它们更新为新的命名约定。

Listing 10-7. cms_apps. py

from cms.app_base import CMSApp

from cms.apphook_pool import apphook_pool

from django.utils.translation import ugettext_lazy as _

class PollsApp(CMSApp):

name = _("Poll App")

urls = ["polls.urls"]

app_name = "polls"

apphook_pool.register(PollsApp)

逐句通过这段代码,请注意以下几点:

  • 首先我们必须导入CMSAppApphookPool类(apphook _pool 是类的别名)。
  • CMSApp类非常简单:我们的PollsApp将它子类化并设置三个属性:
    • 名字。设置 apphook 名称。这是显示在页面高级属性中的名称。
    • 网址。链接到您的应用urls.py文件。
    • App_name。根据您的INSTALLED_APPS设置,这是应用的名称。
  • 一旦我们创建了 apphook 类,我们就把它添加到 apphook 池中。

保存您的cms_apps.py文件并重启开发服务器,以允许新的 apphook 可用。

Note

请注意,每当我们添加或删除 apphook,更改包含 apphook 的页面的 slug,或者更改包含带有 apphook 的后代的页面的 slug 时,我们都必须重新启动服务器来重新加载 URL 缓存。

接下来,您需要添加一个新页面,并导航到页面➤高级设置。

向下滚动直至找到应用下拉列表,并从列表中选择投票应用。

刷新页面,您会发现 Polls 应用现在可以直接从新的 django CMS 页面获得(图 10-7 )。

A978-1-4842-1669-9_10_Fig7_HTML.jpg

图 10-7。

Polls app hooked to the main menu Note

因为 Polls 应用已经通过 apphook 附加到您的项目,所以您不再需要在您的urls.py中引用它。开始url(r'^polls/', . . .的行可以安全删除。

为了完成我们的投票应用在博客网站中的集成,我们希望添加从前端添加和修改投票的能力。幸运的是,django CMS 还允许我们扩展工具栏。

扩展工具栏

当我们向 django CMS 添加应用时,能够从前端编辑器使用它们非常方便。django CMS 提供了轻松扩展工具栏的能力。

与其他扩展一样,django CMS 将在应用的根文件夹中查找一个特殊文件(在本例中为cms_toolbar.py),该文件包含一个或多个类型为CMSToolbar的类。每个类都将被注册为一个工具栏扩展。在这个练习中,在您的投票应用中创建一个新的cms_toolbar.py文件(清单 10-8 )。

Listing 10-8. cms_toolbar. py

from django.utils.translation import ugettext_lazy as _

from cms.toolbar_pool import toolbar_pool

from cms.toolbar_base import CMSToolbar

from cms.utils.urlutils import admin_reverse

from polls.models import Poll

@toolbar_pool.register

class PollToolbar(CMSToolbar):

watch_models = [Poll,]

def populate(self):

if not self.is_current_app:

return

menu = self.toolbar.get_or_create_menu('poll-app', _('Polls'))

menu.add_sideframe_item(

name=_('Poll list'),

url=admin_reverse('polls_poll_changelist'),

)

menu.add_modal_item(

name=_('Add new poll'),

url=admin_reverse('polls_poll_add'),

)

逐句通过这段代码,请注意以下几点:

  • 首先我们必须导入CMSToolbarToolbarPool类(toolbar _pool 是类的别名)。注意与前面使用 apphooks 的例子的相似性。django CMS 类遵循一个通用的结构,这使得使用和记住每个类更加容易。
  • 我们在PollToolbar类中子类化CMSToolbar
  • 注意,这次我们使用了@register装饰器(@toolbar_pool.register)。我们可以很容易地在文件末尾使用toolbar_pool.register(PollToolbar)
  • 我们设置了watch_models,每当通过前端编辑器创建或保存实例时,它允许前端编辑器将用户重定向到模型实例get_absolute_url
  • 然后我们定义一个populate()方法,将一个项目添加到菜单中。populate()方法检查我们是否在属于这个应用的页面中,如果是,它做三件事:
    • 如果没有菜单,则创建一个菜单。
    • 添加一个菜单项,将所有投票列为侧框(选中时将从 Django admin 调用polls.changelist())。
    • 添加一个菜单项来添加一个新的投票作为一个模态窗口(选中时将从 Django admin 调用polls.add())。

保存cms_toolbar.py文件,一旦开发服务器重启,你的网站应该看起来如图 10-8 (注意你必须在投票页面上才能看到)。

A978-1-4842-1669-9_10_Fig8_HTML.jpg

图 10-8。

Polls app added to the toolbar

选择“添加新投票”,将弹出一个新窗口或选项卡(图 10-9 ,允许您输入新投票。

A978-1-4842-1669-9_10_Fig9_HTML.jpg

图 10-9。

Adding a new poll from the django CMS toolbar

另一方面,选择“投票列表”,将会展开侧边栏向您显示投票列表(图 10-10 )。

A978-1-4842-1669-9_10_Fig10_HTML.jpg

图 10-10。

Polls list sidebar Note

这是一个很基本的例子。django CMS 具有扩展工具栏的广泛能力;例如,您可以将菜单项添加到根目录,但这超出了本书的范围。更多信息,请访问 http://docs.django-cms.org/en/latest/how_to/toolbar.html

自定义插件

我们在第六章和第七章中介绍了 django CMS 可用的一些插件。虽然有插件可以为 django CMS 添加各种功能,但用不了多久,您就会遇到可用插件无法满足的客户需求。当这种情况发生时,是时候创建你自己的定制插件了。

把 django CMS 中的一个插件看作是一种特殊的应用是很有帮助的,它可以放在任何 django CMS 占位符中。在这方面,创建一个插件并不比创建(或添加)一个应用和创建一个 apphook 更难,就像你在本章前面所做的那样。

django CMS 插件有三个部分:

  • 插件编辑器,在每次部署时配置插件。这是插件模型,存储在插件的models.py文件中。
  • 插件发布者。这是你的插件类,它选择呈现给浏览器的内容。这个类驻留在cms_plugins.py文件中,您必须在您的插件应用的根目录中创建这个文件。
  • 插件模板。这是一个标准 django CMS 模板文件。这个文件可以存储在任何地方,但是必须被你的插件类的render_template属性引用。

您会注意到 django CMS 插件设计遵循了与 django 相同的模型-模板-视图结构。对于插件来说,发布者就是视图。为了演示创建一个自定义插件是多么容易,我们将从创建一个自定义插件开始,它将在一个方便的侧边栏导航菜单中显示您的所有博客文章。

侧边栏导航

尽管它在移动友好网站上变得越来越不常见,但大多数用户仍然希望在侧边栏中找到二级菜单和链接(例如,到博客帖子和文章的链接)。左边栏还是右边栏能提供更好的用户体验,这是一个不可能解决的争论。我选右只是因为我喜欢右边的边栏。如果你是一个“左撇子”,请随意使用page.html模板文件。无论你使用哪种模板,本章中的所有代码都可以工作(这也是 MVC 是最佳设计模式的另一个原因)。

开始之前

在我们开始之前,确保你的网页有一个类似图 10-11 的侧边栏。如果没有,您将需要返回到第五章的并确保您已经正确构建了模板,并且它们已经被添加到settings.py中。

A978-1-4842-1669-9_10_Fig11_HTML.jpg

图 10-11。

Right sidebar navigation

为了开始使用我们的定制插件,我们还需要创建一个新的 Django 应用。在 Python 虚拟环境命令提示符下,输入

python manage.py startapp menu_plugin

这将在您的/myblog/目录中创建一个新的 Django 应用。一旦你完成了这两个设置步骤,你就可以创建你的工具条插件了。在本节中,我们将

Create the publisher and template for your plugin.   Add a new placeholder to your page template.   Enhance your plugin by adding a configuration option.

创建插件发布者

因为我们将从一个非常简单的定制插件开始,所以在这个阶段我们不需要模型,所以我们的下一步是创建我们的发布者/视图(清单 10-9 )。然后,在接下来的部分,我们将创建我们的模板(清单 10-10 )。

Listing 10-9. Custom Plugin Publisher (cms_plugins.py)

from cms.plugin_base import CMSPluginBase

from cms.plugin_pool import plugin_pool

from cms.models.pluginmodel import CMSPlugin

from django.utils.translation import ugettext_lazy as _

from myblog.models import Category, CategoryExtension

from cms.models import Title

class MenuPlugin(CMSPluginBase):

model = CMSPlugin

name = _("Menu Plugin")

render_template = "menu_plugin.html"

cache = False

def render(self, context, instance, placeholder):

blogposts = []

for t in Title.objects.all():

if t.page.publisher_is_draft==False:

try:

if str(t.page.categoryextension.category) == 'post':

anchor = (t.title,t.path)

blogposts.append(anchor)

except:

pass

context['blogposts'] = blogposts

return context

plugin_pool.register_plugin(MenuPlugin)

清单 10-9 看起来有点复杂,但实际上很简单;在前面的章节中,您已经看到了大部分内容:

  • 您会注意到这段代码遵循了与 apphooks 和 extensions 类似的格式:导入一些自定义类,设置一些属性,并向池注册插件,以便 django CMS 可以找到它。
  • MenuPlugin类继承了CMSPluginBase并设置了一些必需的属性:
    • 模特。必选。这是插件编辑器,允许自定义插件配置。因为我们在这个阶段没有使用自定义设置,所以我们简单地从CMSPlugin继承。
    • 名字。必需的。将在前端编辑器的插件下拉列表中显示的名称。
    • 渲染模板。必选。插件模板的 URL。由于我们没有提供路径信息,django CMS 将在\menu_plugin\templates中查找这个文件。
    • 缓存。可选。定义我们是否想要缓存插件内容。
  • MenuPlugin类还提供了一个render()方法,将一个contextinstance传递回你的模板。因为这是代码中最复杂的部分,所以接下来我会单独解释。

django CMS render()方法与 django 的render()方法基本相同,因为它返回用给定上下文呈现的给定模板的HTTPResponse对象。

在我们的插件中,模板是menu_plugin.html,我们将元组列表添加到上下文中(blogposts)。复杂性来自于我们需要访问本章开始时对Page模型的扩展的方式。

为了在我们的侧边菜单中创建锚文本和 URL,我们需要访问页面的标题和路径。如果你还记得第九章,titlepath都是Title模型的属性,但是我们的范畴扩展是在Page模型上。我们遵循的逻辑类似于我们在第九章中创建博客菜单时使用的逻辑:

  • 我们遍历所有的Title对象,但是只选择那些已发布的对象(publisher_is_draft==False)。
  • 然后,我们检查类别是否是post,如果是,就在 blogposts 列表中添加一个(title, path)元组。
  • 当页面没有被分配类别时,try/except是阻止 Django 抛出错误所必需的。
  • 然后,我们将 blogposts 列表添加到模板要呈现的上下文中。

Note for advanced users: CMSPluginBase

cms.plugin_base. CMSPluginBase类实际上是django.contrib.admin.options.ModelAdmin的子类。因为CMSPluginBaseModelAdmin的子类,CMS 插件开发者也可以使用几个重要的ModelAdmin选项。这些是最常用的:

  • exclude
  • fields
  • fieldsets
  • form
  • formfield_overrides
  • inlines
  • radio_fields
  • raw_id_fields
  • readonly_fields

然而,请注意,并不是所有的ModelAdmin选项在 CMS 插件中都有效。特别是,changelist功能专用的任何选项都将无效。详见 http://docs.django-cms.org/en/latest/how_to/custom_plugins.html

创建插件模板

接下来,我们需要创建我们的插件模板。在你的menu_plugin应用中创建一个\templates\目录,并将清单 10-10 保存到一个名为menu_plugin.html的文件中。

Listing 10-10. Our Custom Plugin Template (menu_plugin.html)

<ol class="list-unstyled">

{% for anchortext, link in blogposts %}

{% with "/"|add:link|add:"/" as full_url %}

<li><a href="{{ full_url }}">{{ anchortext }}</a></li>

{% endwith %}

{% empty %}

<li>There are no published blog posts</li>

{% endfor %}

</ol>

逐句通过这段代码,请注意以下几点:

  • 我们使用一个for循环来遍历在blogposts中传递给浏览器的元组列表。
  • {% with … %}标签提供了一种简单有效的方法来将一个文本字符串(在本例中是一个正斜杠/)连接到模板变量的开头。Django 的标准标签{% value|add:’<your string>’ %}在这里不起作用,因为不能在前面加上/。
  • 列表中的每个元组都用来构建一个 HTML 锚标记,以显示锚文本和到你的每篇博客文章的链接。

一旦你创建了你的插件模板,你需要做的就是将'menu_plugin'添加到INSTALLED_APPS(在settings.py中)并重启开发服务器。你的新菜单插件现在可以安装到你页面上的任何占位符中了(图 10-12 )。

A978-1-4842-1669-9_10_Fig12_HTML.jpg

图 10-12。

Custom menu plugin added to plugins

向页面模板添加占位符

当然,我们的自定义菜单在页面中间用处不大;我们需要能够将它添加到我们的侧边栏菜单。如果你还记得《??》第五章,我们在页面模板(page.html)中创建了一些虚拟文本作为占位符。我们现在需要用 django CMS 占位符替换这段代码。清单 10-11 显示了您需要对page.html进行的更改。

Listing 10-11. Modified page.html template

. . .

<h4>Latest Posts</h4>

{% static_placeholder "posts" %}

<ol class="list-unstyled"> #delete this line

<li><a href="#">Blogpost 1</a></li> #delete this line

<li><a href="#">Blogpost 2</a></li> #delete this line

</ol>  #delete this line

. . .

刷新你的浏览器,切换到你的一篇博客文章(或者任何有右边栏的页面)。切换到工具栏上的结构模式,你的页面应该有一个文章占位符(图 10-13 )。

A978-1-4842-1669-9_10_Fig13_HTML.jpg

图 10-13。

Posts placeholder in right sidebar

将我们的自定义菜单插件添加到这个占位符,保存它,切换回内容视图,你应该会看到一个功能齐全的右菜单(图 10-14 ),显示你所有的博客文章。

A978-1-4842-1669-9_10_Fig14_HTML.jpg

图 10-14。

Completed right menu with blog posts

虽然我们的右侧菜单现在按设计运行,但它确实有一个缺陷——如果你有数百篇博客文章呢?一个流行的答案是创建一个菜单,提供年和月的存档列表,而不是在一个页面上列出每个帖子。由于本书没有足够的篇幅来构建这样一个详细的模型,我将向您展示一个更简单的解决方案:提供一个插件配置选项来限制列表中显示的博客文章的数量。

向插件添加配置选项

在我们的第一个菜单插件版本中,我们没有为插件创建编辑器(model.py)。为了使我们的菜单插件可配置,我们将为我们的插件创建一个自定义模型,这样我们就可以设置有多少博客文章将显示在右边的菜单中。

我们将开始创建你的新插件模型(清单 10-12 )。将该文件保存到\menu_plugin\models.py

Listing 10-12. Menu Plugin ( models.py)

from cms.models.pluginmodel import CMSPlugin

from django.db import models

class MaxEntries(CMSPlugin):

max_entries = models.SmallIntegerField(default=0 , A978-1-4842-1669-9_10_Figa_HTML.jpg

verbose_name='Maximum Entries')

这个代码应该很容易理解:

  • MaxEntries类是CMSPlugin类的子类。
  • 我们正在设置一个配置字段(max_entries),它将保存菜单中允许的最大条目数。我们使用默认值零;这将对应于无限的条目。当我们开始修改模板时,您将看到我们是如何实现这个逻辑的。

我们还需要对我们的cms_plugins.py文件进行一些修改(清单 10-13 )。我用粗体显示了这些变化。

Listing 10-13. cms_plugins.py Updated to Use New Model

. . .

from myblog.models import Category, CategoryExtension

from cms.models import Title

from .models import MaxEntries

class MenuPlugin(CMSPluginBase):

model = MaxEntries

name = _("Menu Plugin")

render_template = "menu_plugin.html"

cache = False

def render(self, context, instance, placeholder):

categoryID = Category.objects.get(category='post')

posts = CategoryExtension.objects.filter(category_id=categoryID)

blogposts = []

for post in posts:

if not Title.objects.get A978-1-4842-1669-9_10_Figa_HTML.jpg

(page_id=post.extended_object_id).publisher_is_draft:

anchor = A978-1-4842-1669-9_10_Figa_HTML.jpg

((Title.objects.get(page_id=post.extended_object_id).title),)

anchor += A978-1-4842-1669-9_10_Figa_HTML.jpg

((Title.objects.get(page_id=post.extended_object_id).path),)

blogposts.append(anchor)

context['instance'] = instance

context['blogposts'] = blogposts

return context

plugin_pool.register_plugin(MenuPlugin)

我们在本章的前面已经详细研究了这个文件,所以我将只解释修改。我们执行以下操作来将新的编辑器添加到菜单插件中:

  • 导入MaxEntries模型。
  • 将我们的插件模型从通用的CMSPlugin改为我们的MaxEntries模型。
  • 当插件代码被调用时,将模型的一个实例传递回浏览器。这个实例将包含我们的MaxEntries字段,因此它可以被模板的渲染逻辑使用。

现在我们已经创建了新的插件编辑器,我们需要更新数据库以包含插件模型。在 Python 虚拟环境命令提示符下,输入

python manage.py makemigrations

这将为您的新插件模型创建一个迁移。然后,我们需要迁移数据库以包含您的新模型:

python manage.py migrate

一旦您完成了迁移并刷新了浏览器,您的插件现在应该有一个MaxEntries配置选项。回到你的博客页面,编辑你之前添加的菜单插件。你的编辑器窗口现在应该有一个最大条目选项(图 10-15 )。

A978-1-4842-1669-9_10_Fig15_HTML.jpg

图 10-15。

Maximum Entries configuration option

因为我们在这个阶段只有几个博客条目,为了测试我们的更改,将这个设置为 1 并保存插件。

接下来,我们必须更新我们的插件模板,以便它在菜单中显示正确数量的条目(清单 10-14 )。变化以粗体显示。

Listing 10-14. Modified menu_plugin.html

<ol class="list-unstyled">

{% for anchortext, link in blogposts %}

{% with "/"|add:link|add:"/" as full_url %}

{% if instance.max_entries == 0 %}

<li><a href="{{ full_url }}">{{ anchortext }}</a></li>

{% elif forloop.counter <= instance.max_entries %}

<li><a href="{{ full_url }}">{{ anchortext }}</a></li>

{% endif %}

{% endwith %}

{% empty %}

<li>There are no published blog posts</li>

{% endfor %}

</ol>

清单 10-14 中的基本逻辑与清单 10-10 中的相同,只是增加了一条if … elif语句。这个新代码基本上是说,如果max_entries是零(0),为所有的博客文章创建锚点;否则,仅在当前计数小于或等于max_entries时创建锚点。

刷新你的浏览器,假设你将max_entries设置为 1,你将只能在菜单中看到第一篇博客文章。编辑你的菜单插件,把max_entries改成 0,保存插件,刷新浏览器,两篇博文都会重新出现。

摘要

在这一章中,我们探讨了 django CMS 的一些更高级的特性。您学习了如何扩展PageTitle模型,以及如何向我们的项目添加 Django 应用和创建 apphook。我们使用 Django 教程中的 Polls 应用来演示应用和 apphooks 是如何被构建并集成到 django CMS 项目中的。

我们还扩展了工具栏,这样我们就可以从前端访问我们的新应用。最后,我们学习了定制插件是如何构建的,并将我们的知识用于为我们的博客站点创建合适的侧边栏菜单。

这一章也是我们对 django CMS 介绍的结尾。我们在这 10 章中涉及了大量的内容;现在你应该对 django CMS 有了足够的了解,能够构建自己的高性能专业网站。

在这么说的时候,你也应该注意到这仅仅是你与 django CMS 之旅的开始。因为这是一本介绍性的书,所以我无法对许多更深入的主题进行更详细的探讨。这本书更多的是介绍 django CMS 的工作原理,而不是用 django CMS 构建专业网站的最佳实践。

如需更多参考资料和下一步该怎么走的指示,请查看第十一章的部分,该部分被恰当地称为后续步骤…

十一、后续步骤

我们已经在这本书里涵盖了相当多的内容,足以让你在 django CMS 中建立专业质量的网站。然而,这本书只是对 django CMS 的一个介绍,如果你想在这个系统中发展专业的编程技能,还有更多东西需要学习。

在这一章中,我将为您提供技巧、链接和指针,告诉您下一步可以去哪里继续您的 django CMS 之旅。我将特别介绍:

  • 部署 django CMS
  • 链接到更高级的 django CMS 主题:
    • 了解菜单系统
    • 创建多语言网站
    • 测试 django CMS
  • 以下社区站点和帮助资源的列表:
    • 决哥 CMS
    • Django
    • 计算机编程语言

本章中的信息并不详尽,因为开源社区一直在变化,所以当您读到本文时,其中一些可能已经过时了。经常检查来源,并关注社区的言论;总的来说,Django 和 django CMS 社区非常活跃,非常愿意为新来者指明正确的方向。

部署

在本书中,我们一直使用 Django 开发服务器来开发和测试我们的项目。虽然开发服务器在您创建网站时非常方便,但它并不意味着要用于生产。它不安全,速度慢,而且不能一次处理多个查询。

我们也只使用 SQLite 作为我们的数据库。虽然 SQLite 对于小型站点和本地部署来说绰绰有余,但对于生产网站来说,它被认为不够健壮或可伸缩。PostgreSQL 和 MySQL 被推荐用于生产站点,其中 PostgreSQL 是 Django 项目推荐的首选。

使用 django CMS,您有三个部署选项(按难度递增顺序排列):

Deploy automatically using Aldryn.   Deploy on a host that supports Django.   Build and deploy to your own server (external or internal).

除非有非常具体的需要,否则不推荐方案 3;如果您想要一个正确配置的服务器,能够处理 Python 长时间运行的流程,那么有一些注意事项。最好将 Python 服务器的后端配置留给知道它们在做什么的外部主机。

因为可能有大量的配置,所以在本书中我不会讨论最后一个选项。如果你真的想走这条路,请参考本章后面列出的 Django 和 django CMS 资源。

与 Aldryn 一起部署

Aldryn 是 Divio(django CMS 的创建者)创建的内容管理平台,专门用于支持部署 django CMS 应用。Aldryn 平台提供

  • 自动化部署
  • 作战
  • 共享团队访问
  • 第三方附加包的自动安装(包括依赖性管理)和集成
  • 通过 web 界面或基于桌面的应用进行管理

Aldryn 与标准主机中的预期不同。Aldryn 不仅仅提供一个工具堆栈和托管 Django 应用的地方,而是创建了一套基于用户角色的工作流:

  • 对于内容创建者,Aldryn 提供了一个控制面板来管理 django CMS 网站。除了我们在本书中提到的所有功能,控制面板还提供了真正有用的功能,例如在网站上线前运行网站的测试服务器,以及大量预装的插件和内容。
  • 对于前端开发人员,Aldryn 提供了一个桌面应用,支持本地文件存储库和生产服务器之间的实时链接。这使得网站设计和应用的开发变得很容易,而不需要运行 FTP 服务器,也不需要提交给 GitHub 这样的外部存储库。
  • 对于后端开发人员,Aldryn 提供了运行本地构建和部署站点的命令行工具。

我不会在这里使用 Aldryn 进行部署;如果您希望进一步了解 Aldryn 的选项,请参见帮助页面( http://www.aldryn.com/en/help/ ),完整文档请参见 http://docs.aldryn.com/en/latest/index.html

部署在 Django 主机上

就简单性而言,Aldryn 的下一个最佳选择是在明确支持 django 的主机上部署 django CMS 网站。一个简单的网络搜索“Django 主机”将会出现数百个支持 Django 的主机,或者,对于 Django 贡献者维护的精选列表,请参见 https://code.djangoproject.com/wiki/DjangoFriendlyWebHosts

一个好的主机至少应该具备以下所有条件:

  • 1gb 专用 RAM(越多越好)
  • SSH 访问,这样您就可以针对您的服务器运行脚本
  • 定期备份您的站点和数据库
  • 用于定期重启服务器的自动化脚本(防止锁定)

许多更好的主机还提供了一个新的 Django 应用的“一键”安装,该应用带有一个预配置的数据库。

在支持 django 的主机上安装一个新的 django CMS 项目通常不会比运行您在第二章中运行的相同脚本更复杂。然而,仍然有一些警告;有些与 Django 有关,有些可能是由您的主机上的配置引起的。除了您选择的主机之外,在任何主机上部署 Django 的最佳资源是 Django 项目本身。可以在以下位置找到部署选项和说明:

https://docs.djangoproject.com/en/1.8/howto/deployment/

对于与安装 django CMS 相关的部署选项,请参考

http://docs.django-cms.org/en/latest/how_to/install.html

django CMS 高级版

django CMS 的许多特性在一本介绍性的书中是不可能深入介绍的。特别是,django CMS 有三个特性值得您深入研究:

The menu system   Managing multilingual sites   Testing

菜单系统

尽管我们探索了 django CMS 菜单系统的一些重要特性,但是没有足够的空间来深入研究这个强大的工具。如果您想深入了解菜单系统的工作原理,请参阅

http://docs.django-cms.org/en/latest/topics/menu_system.html

文档中也有许多关于菜单系统的参考资料:

http://docs.django-cms.org/en/latest/reference/navigation.html

多种语言

django CMS 支持开箱即用的国际化,支持多语言 URL 和页面的多语言版本。有关完整的参考,请参见

http://docs.django-cms.org/en/latest/topics/i18n.html

测试

所有专业应用在部署之前都需要经过彻底的测试。django CMS 中的测试使用 django 的测试套件:

https://docs.djangoproject.com/en/1.8/topics/testing/

测试 django CMS 扩展时需要考虑一些额外的约束,因为它们不能通过urls.py访问。有关测试 django CMS 扩展的信息,请参见

http://docs.django-cms.org/en/latest/how_to/testing.html

获得帮助

幸运的是,django CMS 拥有与它所基于的开源项目相同的充满活力和忠诚的社区支持它:Python 和 django。以下是每个项目的一些主要免费资源的简要列表。这个列表还远未完成,但是这些可以被认为是最好的开始。

django CMS 资源

django CMS 的主要参考资料是文档,可以在

http://docs.django-cms.org/en/latest/index.html

在文档站点的“开发与社区”下有许多社区链接 django CMS 上也有几个相当活跃的谷歌群组,还有大量关于 Stack Overflow 的问答( www.stackoverflow.com )。

如果你想玩 django CMS 的试玩,而不必下载或安装代码,在 http://demo.django-cms.org 有一个不错的 django CMS 试玩。

这本书发布后不久,我也会在 www.masteringdjango.com/djangocms 发布一些支持这本书的免费资源。

Django 资源公司

Django 项目可能拥有关于 Django 的最全面的资源:

https://docs.djangoproject.com/en/

此链接将带您到文档的最新版本。在这一页的顶部寻找一直受欢迎的 Django 教程的链接。从 Django 项目网站(或搜索互联网)开始,寻找其他流行的 Django 资源。以下是我写作时的一些佳作:

Python 资源

Python 是一个非常成熟的项目,因此有成千上万的免费(和付费)资源可用。一个很好的起点是 Matt Makai 在 Full Stack Python ( http://www.fullstackpython.com/best-python-resources.html )编译的列表。我建议你从马特的清单开始,从那里开始。

如果你想了解 Python 2 和 Python 3 的区别,最好的起点是 https://wiki.python.org/moin/Python2orPython3

摘要

在这一章中,我列出了一些资源来帮助你开始使用 django CMS。这个列表并不全面,但是考虑到开源环境不断变化的本质,它提供了一个起点,我希望这将是一个有价值的编程职业。

你现在已经到了这本书的结尾。我希望你像我喜欢写它一样喜欢学习这些材料,并祝你未来的编程之旅一切顺利!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值