Django-CMS-入门指南-全-
Django CMS 入门指南(全)
一、使用 CMS
Electronic supplementary material The online version of this chapter (doi:10.1007/978-1-4842-1669-9_1) contains supplementary material, which is available to authorized users.
在第一章中,我们将从较高的层次上了解什么是内容管理系统(CMS ),并介绍 django CMS:一个基于 django 框架的现代内容管理系统。
我们将从内容管理的简短历史开始,介绍旧的基于纸面的系统的数字版本是如何发展的,以处理每天每分钟在世界各地传播的大量信息。
我将以本书内容的大纲和你将学到的东西的总结来结束这一章。
简史
回到过去的互联网时代(10 年前),从静态的 HTML 网站到更加动态的交互式网站有一个很强的趋势。这对用户来说很好,但是对网页设计者来说却是一个特殊的挑战。为了迎接挑战,大多数专业网站都是以一种特殊的方式建立的:
- 设计师将创建一个网站的整体设计。
- 设计师将与开发人员合作,将设计分割成一个网站模板,该模板将是普通 HTML 和程序代码的混合;程序代码提供网站的交互功能。
- 然后,设计师将与内容创建者(通常是客户)合作,将网站内容合并到模板中,复制模板并为网站的每个页面创建内容。
在非常小的网站上,这些角色可以由一个人来完成,但是对于较大的网站来说,整个团队的设计者、开发者和内容创建者都需要参与来制作一个复杂的网站。
这种设计方法有一个主要缺陷——代码、内容和设计元素的混合意味着对一个元素的任何更改都有可能影响到其他元素。其后果可能从简单的格式错误到网站功能的重大故障。
这个问题的解决方案是内容管理系统(CMS),这是一套早在互联网出现之前就已经存在的方法和流程。
内容管理 101
内容管理是对信息(内容)的系统化管理。理解内容管理的一个简单方法是使用一个例子—这本书:
- 作者(我)会把我的草稿交给一个编辑,他会和我一起确保手稿可以交给出版商。
- 出版商将批准最终的手稿出版。
- 然后,出版商会将布局合理的手稿发送给印刷商,印刷商会印制你现在手里拿着的这本书。
当然,实际的过程比这个序列所暗示的要复杂得多,也更具协作性,但是需要注意的重要一点是,过程中的每个人都扮演着一个角色,并且可以独立于其他人而发挥作用;出版商不必知道作者的手艺,作者也不必了解如何印刷一本书。
内容管理角色
网站 CMS 需要的角色类似于制作一本书所需的角色:
- 作者创建文章和页面内容,并显示在网站上。
- 编辑获取作者创作的内容,并对其进行编辑,以适应网站的风格和上下文,并对拼写和语法进行任何更正。编辑通常在网站 CMS 上扮演发布者的角色;通过运行在服务器上的 CMS 软件标记准备向公众显示的内容。
- 尽管越来越多的人倾向于购买现成的模板来满足网站所有者的设计目标,而不是雇佣设计师来创建定制的外观,但设计师在创建网站的整体视觉呈现方面仍然扮演着重要的角色。
- 网站管理员负责网站的后端——为其他用户分配角色、维护内容以及应用备份和更新。在某些情况下,网站管理员也是开发人员——编写代码来改进网站的功能——尽管这种情况越来越少见,您将在下一节中看到。
剖析现代合作医疗
几乎在所有情况下,现代 CMS 都是一个计算机应用,可以是桌面的,也可以是基于云的(或者是两者的结合)。它们允许轻松组织内容,并提供创建、编辑和发布内容的工具。它们使用数据库和文件系统存储来提供灵活和可扩展的数据存储;现代 CMS 能够处理从两页网站到拥有数百万页内容(如在线新闻)的大规模内容发布平台的一切事情。
绝大多数现代网站都在运行某种形式的内容管理系统。WordPress 是历史最悠久、最受欢迎的网站,大约有五分之一的网站运行在互联网上。CMS 软件近年来在普及性和功能性方面呈指数级增长。
CMS 设计的当前艺术状态将我们已经讨论过的所有内容管理工具与三种设计理念相结合,以创建功能丰富、可伸缩且响应迅速的网站:
- 模型/视图/控制器(MVC)架构。解释 MVC 超出了本书的范围,但它是一种软件设计模式,是模块化方法的缩影。在 MVC 中,内容、设计和代码在网站中是物理分离的,而不仅仅是概念上的分离。
- 使用外部应用来增加功能。现代 CMS 允许您“插入”由其他开发人员编写的提供新功能的附加程序,而不是编写新代码,而不是自己编写代码。这些程序从改变格式的简单插件到成熟的应用都有。使用外部应用不仅增加了 CMS 的可靠性,还极大地降低了成本,因为一个开发者可以向许多需要该功能的不同网站出售相同的插件或应用。
- 移动友好。在全球大多数国家,智能手机和平板电脑的使用量超过了台式机。据预测,在未来几年内,向移动计算的转移将继续增加。众所周知,现代 CMS 必须通过提供所谓的响应界面来支持移动设备,该界面可以自动调整网站的内容,以适应查看网站的设备。
django CMS 与其他 CMS 相比有一些关键优势——最明显的是在模块化和功能分离方面比 WordPress 等程序有了显著的改进,后者仍然使用在页面上混合内容和代码的旧模式。其他优势包括:
- 它是多语言的。
- 它支持多个网站。
- 它使用开箱即用的引导程序来支持移动设备。
- 它可以连接到多个数据库。
- 其灵活的页面模型和格式插件的可用性将您从死板的模板布局中解放出来。
- 它提供开箱即用的内容调度。
- 它提供了发布和管理角色的明确分离。
- 它可以很容易地与其他 Django 应用集成,而不需要进行大的修改。
- 其基于插件的设计允许轻松集成电子邮件和第三方应用和内容服务。
django CMS 将所有这些设计元素结合到一个干净、简单的界面中,对于内容创建者、编辑和管理员来说,这是一个很好的界面。django CMS 建立在 django 的基础上,Django 是一个网络内容管理系统,最初是为一家大型美国报纸开发的。它于 2007 年作为开源软件发布,由于其健壮的体系结构和可伸缩性,一直在建立强大的用户基础。
你将学到什么
有了 django CMS,您可以轻松快速地构建功能丰富、无 bug 的网站。这本书将带你经历学习过程;最后是一个基本的博客网站,你可以用它来写自己的博客,或者向雇主展示你的技能。
这本书的目的是教你 django CMS 的设计方法,以及如何用它快速专业地建立一个功能网站;它不是为了给你深入的 django CMS 的技术知识而设计的。为了更深入的理解和更高级的主题,我在第十一章中提供了资源和链接。
让你感受一下接下来会发生什么:
- 在第二章中,你将学习如何在你的电脑上安装 django CMS 及其依赖项。
- 在第三章中,我将提供 django CMS 的概述,包括它的设计理念以及界面和功能的高级视图。
- 在第四章中,您将了解 django CMS 模板,以及它们如何利用 django 的模板引擎和引导程序来创建快速、干净、移动友好的网站。
- 在第五章中,我们将为您的网站构建一整套响应式模板。我将带您浏览每一行代码,这样您就可以彻底掌握如何构建自己的代码。
- 在第六章和第七章中,我们将探索赋予 django CMS 灵活性和强大功能的关键工具:插件。我们将涵盖所有内置插件以及一些重要的第三方插件,这些插件可用于 django CMS。
- 在第八章中,你将学习用 django CMS 组织和管理内容。我们将看看 django CMS 中的用户管理、用户角色和发布周期。在第八章的最后,你将完成一个为你的网站创建内容的练习。
- 在第九章中,你将学习 django CMS 中的菜单和导航。您将学习如何将面包屑导航添加到您的站点,安装社交媒体共享功能,以及生成站点地图。我还将向您展示如何创建自定义菜单。
- 在第十章中,我们将深入探讨 django CMS 的一些更高级的特性:扩展页面和标题模型,扩展工具栏,以及创建定制插件。我们将完成一个自定义插件,你可以用它来为你的网站创建一个右边栏菜单。
- 最后,在第十一章中,我会给你一些提示和资源链接,继续你的 django CMS 之旅。django CMS 可以做很多事情,还有一些我在本书中没有涉及的高级主题。第十一章将帮助你掌握 django CMS 的后续步骤。
摘要
在本章中,我们简要探讨了内容管理的历史以及现代基于计算机的内容管理系统(CMS)是如何工作的。我们已经了解了 django CMS 如何融入这个生态系统,并强调了它的一些主要优势。
我以这本书的简要概述和你可以期待的结尾结束。在下一章中,您将通过安装 django CMS 应用及其依赖项开始使用 django CMS。
二、安装 django CMS
django CMS 是一个基于 Django web 框架的基于 web 的开源内容管理系统。它由位于苏黎世的商业网站开发公司 Divio AG 维护。但是在你开始学习如何使用 django CMS 之前,你必须先在你的电脑上安装一些软件。幸运的是,这是一个简单的三步过程:
Install Python. Install a Python Virtual Environment. Install django CMS.
如果这听起来不熟悉,不要担心;在这一章中,我假设你以前从未从命令行安装过软件,我将一步一步地引导你。
虽然 Mac OSX 和 Linux 的用户群一直在增长,但我为大多数使用 Windows 的人写了这一节。您的计算机可以运行任何最新版本的 Windows 操作系统(Windows Vista、Windows 7、Windows 8.1 或 Windows 10)。
这个过程在运行 Mac OSX 和 Linux 的机器上非常相似。如果您使用的是 Mac 或 Linux,不要担心,因为互联网上有大量关于在这些系统上安装 Python 和 django CMS 的说明。有关在这些系统上安装软件的更多信息,请参见第十一章。
Note
Windows 用户,根据您的计算机的配置,您很可能需要以具有管理员权限的用户帐户运行,以便能够安装软件并运行一些命令和命令提示符。
安装 Python
安装 Python 非常简单,但是首先您需要检查 Python 是否已经安装在您的系统上。为此,我们使用一些 Windows 用户可能不熟悉的工具——命令提示符。如果您习惯使用命令提示符,请随意浏览这一部分。
检查是否安装了 Python
命令提示符其实挺有用的。当你学习 django CMS 时,你会经常用到它,所以如果你以前没有用过,现在是时候熟悉一下这个工具了。
要启动命令提示符,需要找到cmd.exe并运行程序。
在 Windows 7 和 Vista 中,单击开始按钮并在搜索程序和文件框中键入cmd。
在 Windows 8.1 和 10 中,在搜索网页和 Windows 框中键入cmd。
在所有版本的 Windows 中,都会出现一个列表—查找名为cmd.exe的文件。点击该文件运行它,你应该会看到一个类似于图 2-1 中的黑框。

图 2-1。
The Windows command prompt Tip
当程序运行时,右键单击任务栏中的 cmd.exe 图标(文本中带有 c:\ _ 的黑色图标)并选择“固定到任务栏”。这样,每当你想运行程序时,你就可以很容易地访问它。
现在我们已经打开了命令窗口,我们需要检查 Python 是否已经安装。这很简单——只需在提示符下键入python,然后按回车键:
C:\Users\YourUsername>python
如果没有安装 Python,您将收到如下消息:
'python' is not recognized as an internal or external command,
Operable program or batch file.
如果安装了 Python,你会得到一个类似于图 2-2 所示的消息,它会打开 Python 交互提示。我们将很快回到 Python 的交互提示。

图 2-2。
The Python interactive prompt Warning
如果您的系统列出的 Python 版本以 2 开头(如 2.7.x),您运行的是旧版本的 Python,需要安装 Python 3,因为本书中的所有代码都是用 Python 3 编写的。如果需要安装 Python 3,请按照下一节的说明进行操作。
完成后,关闭命令窗口。
下载并安装 Python
假设您的系统中没有安装 Python,我们首先需要获得安装程序。进入 https://www.python.org/downloads/ ,点击黄色的大按钮下载 Python 3.x.x
在撰写本文时,Python 的最新版本是 3.4.3,但在您阅读本文时,它可能已经更新了,因此数字可能略有不同。
不要下载 2.7.x 版本,因为这是 Python 的旧版本。本书中的所有代码都是用 Python 3 编写的,所以如果您试图在 Python 2 上运行代码,将会出现编译错误。如果出于某种原因,您必须使用 Python 2 而不是 Python 3,您将需要修改一些代码。在大多数情况下,这就像将__str__()函数改回__unicode__()并将print()函数修改回print语句一样简单;但是,可能会出现其他错误。有关两个版本之间差异的完整参考链接,请参见第十一章。
下载完 Python 安装程序后,转到下载文件夹,双击文件python-3.x.x.msi运行安装程序。
安装过程和其他任何 Windows 程序一样,所以如果你以前安装过软件,这里应该没有问题;然而,有一个非常重要的定制您必须做。
Caution
不要忘记下一步,因为它将解决 Windows 中因不正确映射pythonpath(Python 安装的一个重要变量)而产生的大多数问题。
当安装程序打开定制窗口时,没有选择“将 python.exe 添加到路径”选项;您必须将其更改为“将安装在本地硬盘上”,如图 2-3 所示。

图 2-3。
The Add python.exe to Path option
一旦 Python 安装完毕,你应该能够重新打开命令窗口,并在命令提示符下键入python,得到与图 2-2 相同的输出。现在就这样做,以确保 Python 已经安装并正常工作。
当你在做的时候,还有一件更重要的事情要做。
通过键入 Ctrl-C 退出 Python。在命令提示符下键入以下内容并按 Enter 键:
C:\Users\YourUsername>python –m pip install –U pip
您现在不需要理解这个命令到底是做什么的;简单来说,pip是 Python 包管理器。它用于安装 Python 包:pip实际上是“Pip Installs Packages”的递归缩写。Pip对于我们安装过程的下一阶段很重要,但是首先我们需要确保我们运行的是最新版本的pip,这正是这个命令所要做的。
安装 Python 虚拟环境
计算机上的所有软件都是相互依赖地运行的,每个程序都有它所依赖的其他软件(称为依赖关系)以及它需要用来查找文件和其他需要运行的软件的设置(称为环境变量)。当你在写新软件的时候,这是可能的(也是常见的!)来修改其他软件所依赖的依赖关系和环境变量。这可能会导致许多问题,因此应该避免。
Note
Python 虚拟环境允许您在自己的机器上运行独立的 Python 实例,不应该与虚拟机混淆。后者是允许你运行整个操作系统和应用的软件,就像它们是一台物理计算机一样。
Python 虚拟环境解决了这个问题,它将新软件所需的所有依赖项和环境变量打包到一个文件系统中,该文件系统独立于计算机上的其他软件。Python 中的虚拟环境工具叫做virtualenv,我们使用pip从命令行安装(图 2-4 ):

图 2-4。
Pip installed successfully
C:\Users\YourUsername>pip install virtualenv
一旦安装了virtualenv,你需要为你的项目创建一个虚拟环境(图 2-5 ):

图 2-5。
Python virtualenv active
C:\Users\YourUsername>virtualenv myCMS
在这种情况下,我将新的虚拟环境称为myCMS,但是您可以随意称呼它。一旦virtualenv完成了新虚拟环境的设置,打开 Windows 资源管理器,看看virtualenv为你创建了什么。
在您的主目录中,您将会看到一个名为\myCMS的文件夹(或者您给虚拟环境起的名字)。如果打开该文件夹,您将看到以下内容:
\Include
\Lib
\Scripts
\src
Virtualenv已经为您创建了一个完整的 Python 安装,与您的其他软件分开,因此您可以在不影响系统上任何其他软件的情况下处理您的项目。要使用这个新的 Python 虚拟环境,我们必须激活它,因此让我们返回到命令提示符并键入以下内容:
C:\Users\YourUsername>myCMS\scripts\activate
这将在虚拟环境的\scripts文件夹中运行activate脚本。您会注意到您的命令提示符现在已经更改:
(myCMS) C:\Users\YourUsername>
命令提示符开头的(myCMS)让您知道您正在虚拟环境中运行。我们的下一步是安装 django CMS 项目。
安装 django CMS
安装 django CMS 的第一步是安装 django CMS 安装程序。这是通过pip完成的:
(myCMS) C:\Users\YourUsername>pip install djangocms-installer
然后,我们必须为 django CMS 项目创建一个项目目录,并进入该目录:
(myCMS) C:\Users\YourUsername>mkdir myCMS-tutorial
(myCMS) C:\Users\YourUsername>cd myCMS-tutorial
最后,我们需要安装 django CMS 支持的网站:
(myCMS) C:\Users\YourUsername\myCMS-tutorial>djangocms –p . mysite
不要忘记“.”在-p和mysite之间!
django CMS 安装程序现在会问你几个问题。在大多数情况下,您只需接受默认设置;但是,有些选项您应该更改。我用粗体突出显示了它们。
Database configuration (in URL format) [default sqlite://localhost/project.db]:
django CMS version (choices: 2.4, 3.0, 3.1, stable, develop) [default stable]:
Django version (choices: 1.4, 1.5, 1.6, 1.7, 1.8, stable) [default stable]:
Activate Django I18N / L10N setting (choices: yes, no) [default yes]:
Install and configure reversion support (choices: yes, no) [default yes]:
Languages to enable. Option can be provided multiple times, or as a comma separated list. Only language codes supported by Django can be used here: en
Optional default time zone [default <your timezone>]:
Activate Django timezone support (choices: yes, no) [default yes]:
Activate CMS permission management (choices: yes, no) [default yes]:
Use Twitter Bootstrap Theme (choices: yes, no) [default no]: yes
Use custom template set [default no]:
Load a starting page with examples after installation (english language only). Choose "no" if you use a custom template set. (choices: yes, no) [default no]: yes
Creating the project
Please wait while I install dependencies
##lots more messages…
Creating admin user
Username (leave blank to use '<yourusername>'):
Email address: enter email address
Password: enter a password
Password (again):
Superuser created successfully.
All done!
一旦安装了 django CMS,您应该能够运行您的全新项目了。在您的项目目录中(如果您在安装后直接启动,您应该还在那里),您用以下命令运行 Django 开发服务器:
(myCMS) C:\Users\YourUsername\myCMS-tutorial>python manage.py runserver
一旦开发服务器开始运行,你可以在浏览器中输入 http://127.0.0.1:8000 ,默认的 django CMS 模板将会加载,给你一个类似于图 2-6 的屏幕。

图 2-6。
Success! Tip
Windows 用户可能也想考虑安装 Git BASH,它是 Git for Windows 包( https://git-for-windows.github.io/ )的一部分。大多数在线示例都假设您正在运行某种形式的 Unix,因此安装 Git BASH 将允许您运行 Unix 格式的命令行工具,而无需将示例翻译成 Windows shell 命令。
摘要
在这一章中,我们已经介绍了 Python 和 django CMS 的安装和配置,结果是一个漂亮干净(尽管是空的)的 django CMS 网站。在下一章,我们将探索 django CMS 背后的整体结构和设计理念。
三、django CMS 简介
基于 Django 还有许多其他的 CMS 应用;然而,在撰写本文时,django CMS 是最受欢迎的【1】,并且受到大量用户和开发人员的支持。
就其本身而言,django CMS 并不是一个“即插即用”的网站建设者,非程序员可以选择一个模板,添加一些内容,并在几个小时内建立和运行一个网站。它被特别设计来给开发者和设计者更多的自由来定制他们的网站。
设计原理
可以把 django CMS 想象成一盒乐高积木和一个模型车套件——两者都可以用来建造一辆模型车,但是使用乐高,你几乎可以完全自由地建造任何你喜欢的汽车,而使用套件,你只能得到盒子里的汽车(假设你按照说明操作)。
理解 django CMS 是内容不可知的也是有帮助的,因为它不会对你的内容强加任何固定的结构。django CMS 旨在为您的内容提供发布框架,但是如何构建内容取决于您;您可以自由地做任何事情,从用插件格式化页面上的文本,到放入整个 Django 应用并将它们与 django CMS 菜单和管理挂钩。
django CMS 继承了 django 的大部分设计理念;它执行以下所有操作:
- 实现模型视图控制器(MVC)架构,将表示逻辑与业务逻辑分开。
- 提供可插拔架构,允许轻松添加自包含插件和应用(app ),以扩展网站的功能。
- 默认情况下使用搜索引擎友好的 URL。
- 默认情况下支持多种语言。
为了增强 Django 的内容管理能力,它增加了以下特性:
- 前端编辑—允许结构和内容修改,而不需要专门的管理后端。
- 全触摸界面支持,重点是领先供应商的平板电脑和触摸笔记本电脑。许多手机也可以工作,但你应该注意,django CMS 的触摸功能明确不支持它们。
- 一系列用于常见内容管理任务(如页面编辑)和第三方应用集成(如社交媒体)的预构建插件。
- 所有内容页面的版本控制(历史)。
- 内容创建者轻松的权限管理—可分配的创建/编辑/发布授权。
- 媒体资产管理—文件、图像、视频和动画(Flash)。
当然,没有一个软件包是完美的:django CMS 确实有缺点,有些是因为 django 的局限性,有些是因为 django CMS 的设计方式:
- 它不是为开箱即用的简单内容管理而设计的;你不能像其他 CMS 应用一样,创建一个页面就开始输入内容。您首先需要一个带有占位符的模板;然后,您必须添加至少一个插件,配置插件,并添加您的内容。
- 这对于非常简单的站点来说过于复杂,因为没有简单的方法将 Django 项目从数据库中分离出来,所以即使您不需要数据库,您仍然需要配置一个。
- 在撰写本文时,还没有大量的第三方插件可用。随着 django CMS 越来越受欢迎,可用插件的数量也在不断增加,但是在更成熟的 CMS 应用中有许多功能是现成的,您必须在 django CMS 中自己编写代码。
- 因为 django CMS 和 django 都是正在开发中的开源项目,所以与一些插件和 Django 应用的向后兼容性有时会出现问题。
django CMS 的强大和灵活性很好地弥补了这些缺点。通常,对于构建完全定制的 CMS 比从头构建 CMS 要快得多的应用,您会选择 django CMS,这种应用需要更积极地管理 CMS 的更多技术方面。
django CMS 的结构
django CMS 的结构允许大部分 CMS 管理功能从网站的前端执行,而不是有一个单独的管理后端。django CMS 与大多数其他 cmse 的不同之处在于,它允许您从前端编辑内容和结构,这使得更新、预览和发布基本设计和内容更改变得非常容易。
访问站点编辑器非常简单,只需将字符串?edit附加到主页 URL 上——在我们的示例中,这将是 http://127.0.0.1:8000/en/?edit 。如果您输入的网址正确,您将看到演示网站的首页如图 3-1 所示。

图 3-1。
DjangoCMS home page with edit toolbar displayed
使用您在第一章中输入的管理员用户名和密码登录您的演示网站。登录后,工具栏会变为登录状态,如图 3-2 所示。

图 3-2。
django CMS toolbar changed to edit mode
一旦 django CMS 处于编辑模式,你可以通过下拉菜单访问工具栏中的一系列功能。每个菜单的可用选项将取决于您的访问级别。目前,您以管理员身份登录,因此您将拥有对该站点的完全访问权限。我们将在下一节更详细地探讨工具栏中的功能。
您还可以直接编辑文本和页面结构。将鼠标悬停在(或点击)页面的某些部分会弹出一个上下文编辑链接,允许您编辑内容(图 3-3 )和结构(图 3-4 )。

图 3-4。
Link to edit page structure

图 3-3。
Link to edit page content
你将在第八章中看到如何编辑页面结构和内容。
django CMS 工具栏
对于内容和布局编辑以及网站管理员来说,django CMS 工具栏通过四个下拉菜单提供了管理和更新网站所需的所有工具:
- 站点下拉菜单(默认安装中的 example.com)有许多菜单选项,允许站点管理员管理页面、用户和 Django 管理后端。内容和布局编辑者通常无法访问它。我们将在第八章的中更详细地探讨站点下拉菜单。
- 页面下拉菜单提供对所有页面功能的访问,包括添加页面、编辑、发布和删除页面。根据权限设置,编辑者还可以更改页面模板、页面权限和许多高级设置。第八章也涵盖了下拉页面。
- 历史下拉菜单提供对完整页面历史的访问,能够查看页面更改并恢复到页面的早期版本。更多信息请见第八章。
- 语言下拉菜单允许您管理页面的各种翻译。在这本介绍性的书中,我们将只使用英语,所以我们不会探究这个菜单的功能。
工具栏右侧的四个按钮都与页面结构和编辑相关,将在第八章的中详细介绍。
django CMS 侧窗格
在继续构建我们的演示站点之前,我们还需要了解编辑界面的一个结构元素:侧窗格。如果您选择 example.com➤页面,您将看到侧窗格弹出,如图 3-5 所示。

图 3-5。
The Side pane
几个下拉菜单选项将打开侧窗格,允许您输入附加信息。您会注意到侧窗格右上角的三个小导航选项卡。使用< >箭头显示和隐藏侧面板,使用 X 关闭侧面板。
面向设计者和开发者的 django CMS
网站设计者和开发者会注意到,前端几乎没有什么设计和编码。这是由设计决定的,并遵循与 Django 相同的哲学——设计、代码和内容是三个截然不同的学科,因此需要相互分离。
但是不用担心;django CMS 对于设计人员和开发人员来说和内容编辑人员一样容易使用:
- 对于设计师来说,django CMS 使用一个干净、简单的基于 HTML 的模板系统,不需要任何编码。它还完全支持引导和丰富的内容。第四章和第五章对此有详细介绍。
- 对于开发者来说,django CMS 遵循 django 的可插拔的、面向应用的架构。django CMS 通过插件和 Django apphooks 实现了这一点。我们将在第六章、 7 、 9 和 10 中详细探讨这些话题。
摘要
在这一章中,我们对 django CMS 进行了高层次的观察,查看了它的结构、功能和设计理念。我们研究了它的优点和缺点,并探索了它的设计如何满足设计者和开发者的不同需求。
在下一章中,我们将深入探讨 django CMS 站点模板,向您介绍 django 模板系统的 django CMS 实现,以及它的自定义模板标签,我们将为您自己的博客网站创建站点模板奠定基础。
Footnotes 1
https://www.djangopackages.com/grids/g/cms/
四、网站模板
在这一章中,我们将深入探讨 django CMS 站点模板。我们将从详细回顾 django CMS 模板构建所基于的技术开始。我们将逐步完成 django CMS 安装程序创建的模板,并将它们与您所学的内容联系起来,从而结束这一章。
如果理论一开始让你有点害怕,不要担心;在下一章,我们开始真正有趣的东西,但不要太快跳到前面。一旦你吸收了本章的所有内容,你就再也不会抱怨不懂模板了!
Django 模板 101
django CMS 继承并扩展了 django 的模板系统,因此了解该系统设计背后的核心原则非常重要,即:
- 遗产
- 逻辑和表现的分离
- 展开性
遗产
大多数现代网站都有一个通用的站点范围的设计,其中页面上的某些元素——如页眉、页脚和菜单——在每个页面上重复出现。Django 模板系统使用一种设计模式,其中每个页面都继承了一个基础模板的设计属性,这个模板按照惯例被命名为base.html。(你会在/mysite/templates目录中找到由 django CMS 安装程序创建的base.html模板。)
作为快速复习,让我们看看 Django 的模板继承是如何工作的。基本模板是一个完整的 HTML 文件;清单 4-1 展示了一个base.html文件的最小但有效的实现。
Listing 4-1. A Minimal base.html File
<!doctype html>
<html>
<head>
<title>{% block title %}Default Title{% endblock title %}</title>
</head>
<body>
{% block content %}
This is the content in the base template
{% endblock content %}
</body>
</html>
图 4-1 显示了这个基本模板将如何在浏览器中呈现。

图 4-1。
Rendering of a simple base template
这个最小的例子介绍了 Django 继承背后的关键元素:block 标签。在继承自base.html的子模板中,{%block ... %}和{%endblock ... %}标签之间的任何内容都可以被覆盖。例如,让我们考虑一个基本的子模板(清单 4-2 )。
Listing 4-2. Basic Child Template
#child.html
{% extends "base.html" %}
{% block title %}Title of Child Page{% endblock title %}
{% block content %}
<p>This text will override the block content tag in base.html </p>
{% endblock content %}
图 4-2 显示了子模板将如何在浏览器中呈现。请注意,页面的内容和标题已经在子模板中被覆盖。

图 4-2。
Child template overrides the block tags in base template
在这里发挥全部魔力的元素是{% extends "base.html" %}标签。这告诉模板呈现器child.html扩展(继承)了base.html模板。当渲染器在子模板中找到与基础模板相同的块标记时,子模板中的块将被发送到浏览器。
或者换句话说,当child.html在你的浏览器中呈现时,它的标题和内容块将覆盖基本模板中的块,从而允许每个页面呈现定制内容,而不必复制或修改整个站点的内容。很酷,是吧?
要了解继承在真实的模板中是如何工作的,请看一下mysites/templates中的page.html和feature.html。不要担心其中的许多内容现在没有意义,因为我们很快就会更详细地浏览这些模板。
逻辑和表现的分离
Django 不允许在页面模板中执行任意代码。这意味着您不能在模板中编写代码、分配变量或执行任何类型的程序逻辑。这有一些很好的理由,我在第一章中提到了。然而,关于设计最重要的,也是值得再次提及的是 Django 假设(正确!)大多数网页设计师都不是程序员,不要把程序代码和 HTML 混在一起是非常重要的。
然而,Django 确实提供了许多模板标签和模板过滤器,允许您做出与表示相关的决定。如果您对 Django 比较陌生,那么内置的模板系统非常简单,由四种主要的标记类型组成:
- 变量的格式为
{{ value }}。当模板引擎遇到一个变量时,它会对它求值并用结果替换它。变量可以是任何 Python 数据类型。 - 过滤器的格式为
{{ value|filter }}。过滤器用于修改变量的显示方式。 - 标签的格式为
{% tag %}。它们非常通用,模板引擎可以使用它们来- 在输出中创建文本
- 控制程序流程并执行逻辑
- 加载外部信息
- 注释的格式为
{# comment #}。它们的功能类似于 HTML 注释:注释块中的任何文本都将保留在模板中,为模板设计者或程序员提供信息,但不会呈现给浏览器。这种格式仅适用于单行注释;对于多行,你必须使用{% comment %}...{% endcomment %}块标签。
Django 的模板标签提供了许多有用的函数来显示应用中的数据。例如,for/endfor标签允许简单地迭代列表项,而if/else/endif标签允许简单地决定显示什么内容。Django 的模板过滤器允许对数据进行排序、过滤和格式化。过滤器直接应用于由管道字符分隔的模板变量(在大多数键盘上位于\上方);比如{{ title|upper }}。您也可以创建自己的自定义模板标签库。自定义模板标签超出了本书的范围;然而,如果你有兴趣,更多信息可以在 https://docs.djangoproject.com/en/1.8/howto/custom-template-tags/ 找到。表 4-1 总结了 Django 最常用的模板标签和过滤器。
表 4-1。
Common Django Template Tags and Filters
| 普通 Django 模板标签 | 描述 | | --- | --- | | `{% if %}` `{% endif %}` | 如果`statement`为真,则呈现标签之间的内容。例如:`{% if article_list %}` `There are some articles published
` `{% endif %}` | | `{% elif %}` `{% else %}` | 可选标签为`if/endif`流量控制标签。提供与 Python `elif`和`else`语句相同的功能。例如:`{% if article_list %}` `There are articles published
` `{% elif article_drafts %}` `There are some articles in draft
` `{% else %}` `No articles sorry!
` `{% endif %}` | | `{% for %}` `{% endfor %}` | 允许轻松迭代一系列项目。例如:`- ` `{% for article in article_list %}` `
- {{ article.title }} ` `{% endfor %}` `
No articles sorry!
` `{% endfor %}` | | `upper``lower` | 大写、小写和标题大小写格式。示例:`{{ title|upper }}`如果`title`是“开始 DJANGO”,则输出将是“开始 Django” | | `date` | 如果变量是 datetime 对象,它将根据格式字符串进行格式化。示例:`{{ today|date: "D d M Y" }}`将输出 2015 年 9 月 19 日星期六。`date`格式字符串遵循与 PHP 格式字符串相同的约定。实现这一点是为了让设计人员更容易从 PHP 切换到 Django。 | | `Default` | 如果变量为空,则输出默认值。示例:`{{ value|default:"empty" }}`如果`value`为空,输出将是字符串“empty” | | `first` `last` | 返回列表中的第一个(或最后一个)项目。示例:`{{ article_list|first }}`将输出文章列表中的第一篇文章。 | | `truncatechars` `truncatewords` | 将变量截断到指定的字符/单词数。例如:`{{ title|truncatechars:7 }}`会将“这是标题”截断为“这是”,而`{{ title|truncatewords:3 }}`会输出“这是” |这只是所有可用的 Django 模板标签和过滤器的一小部分。完整列表请见 http://masteringdjango.com/django-built-in-template-tags-and-filters/ 。
展开性
Django 的模板系统被设计成可扩展的。现在详细说明 django 如何实现这一点并不重要,但是理解 django CMS 如何利用 Django 的可扩展性是很重要的;也就是说,有几个扩展的标记库,包括:
cms_tagssekizai_tagsmenu_tags
CMS 标签
django CMS 实现了 19 个自定义模板标签(列于表 4-2 )。为了加载 django CMS 标签,我们使用 django 的load模板标签:
表 4-2。
django CMS Custom Template Tags
| django CMS 自定义标签 | | | --- | --- | | `placeholder``static_placeholder``render_placeholder``render_uncached_placeholder``show_placeholder``show_uncached_placeholder``page_lookup``page_url``page_attribute` | `render_plugin``render_plugin_block``render_model``render_model_block``render_model_icon``render_model_add``render_model_add_block``page_language_url``language_chooser``cms_toolbar` |{% load cms_tags %}
这个加载标签必须放在你的base.html文件的顶部。
我们将在本书的后面使用许多这样的标签,但是现在我们来看看三个最重要的自定义标签:
placeholderstatic_placeholdercms_toolbar
占位符
标签定义了模板中的一个占位符。占位符用作编辑页面时放置插件的容器;例如,这个标签:
{% placeholder "content" %}
在模板中放置一个占位符,当您第一次添加基于模板的页面时,该占位符将呈现为一个空容器。然后,您可以从前端编辑器向容器添加插件,以在页面上呈现内容。
占位符接受编辑器中可用的任何插件,插件可以嵌套。因此,例如,您可以添加一个多列插件来添加两列,然后用一个文本插件填充每一列,以在页面上呈现两列文本。您将在本书的稍后部分看到如何做到这一点。
占位符的名称无关紧要。我在这里使用了名称"content",因为最好的做法是使你的变量名尽可能具有描述性,但是你也可以把占位符称为任何东西。关于占位符名称的主题,请注意,占位符对于页面是唯一的,因此您可以在两个不同的页面上有一个名为"content"的占位符,它们将引用不同的对象。如果你想让一个占位符为多个页面所共有,你需要使用static_placeholder。
如果占位符为空,还可以使用or参数呈现附加内容。要使用r,必须添加一个{% endplaceholder %}结束标签。例如:
{% placeholder "content" or %}Coming Soon!{% endplaceholder %}
placeholder标签也可以从它上面的任何有同名占位符的父页面继承。所以包含这个标签的模板:
{% placeholder "content" inherit %}
将从包含名为"content"的占位符的继承树中它上面的第一个父页面继承content占位符。
可以将inherit与or结合起来,为继承的页面创建一个完整的回退解决方案:
{% placeholder "content" inherit or %}No content anywhere!{% endplaceholder %}
静态 _ 占位符
static_placeholder标签在功能上与placeholder标签相似;但是,它可以在模板中的任何地方使用,通常用于显示站点上任何地方的内容,包括在其他应用中。例如,如果我们创建这个占位符:
{% static_placeholder "footer" %}
并把它放在一个模板文件中(不管是哪一个),添加一个文本插件和来自前端编辑器的文本"Copyright 2015",每个实现了名为"footer"的静态占位符的页面也会显示"Copyright 2015"。
当然,将静态占位符放在您的base.html文件中更有意义,尤其是如果它是页脚或页眉之类的东西,但是并不要求您这样做。另一个好处是,如果你决定改变占位符的内容,你可以从任何页面编辑它,它会自动更新其余的内容;您不必返回到基础页面进行编辑。
static_placeholder标签还带有or参数和一个额外的site参数,以允许静态占位符在多站点安装中特定于站点。例如:
{% static_placeholder "footer" mysite or %}
No footer on mysite.
{% endstatic_placeholder %}
注意,多站点安装超出了本书的范围,但是这个例子确实给出了 django CMS 的简单可伸缩性的概念。
cms _ 工具栏
定制标签cms_toolbar使模板引擎能够呈现 django CMS 工具栏。cms_toolbar标签应放在base.html中的<body>标签之后,并且不得包含在块标签中:
# template header information
. . .
<body>
{% cms_toolbar %}
# rest of the template
. . .
关斋标签
Django-sekizai 是一个第三方库,它使用块来呈现 CSS 和 JavaScript 之类的静态媒体文件(sekizai 是日语中“块”的意思)。Sekizai 允许设计人员在模板中扩展和/或添加 CSS 和 JavaScript 文件,而无需编辑底层 Python 文件。
Django-sekizai 提供了css和js名称空间,允许 Django 视图在不改变模板的情况下添加媒体;例如,cms_toolbar定制模板标签会自动将 CSS 和 JavaScript 添加到 sekizai 名称空间中,而无需修改模板。Django-sekizai 还会自动删除重复的内容,因此当媒体文件被多次包含时不会有膨胀的风险。
因为 Django-sekizai 是 django CMS 所必需的,所以安装程序会将必要的模块和设置添加到您的项目中。要将 Django-sekizai 包含在您的模板中,您可以将它加载到您的base.html文件的顶部:
{% load sekizai_tags %}
Django-sekizai 使用起来极其简单;要将它添加到您的模板中,您只需要两个标签:
render_blockaddtoblock
然而,为了让 Django-sekizai 工作,你必须遵守一些规则
render_block标记不能在包含的模板中;它们必须在您的base.html文件中。render_block标记不能放在 Django 块标记内。- 如果
addtoblock在一个扩展模板中使用(使用{% extends ... %}标签),它必须包含在块标签中。
Caution
请密切注意这些规则,因为在使用 Django-sekizai 时,它们通常是“无效块标签”错误的来源。更多信息请参见 https://django-sekizai.readthedocs.org/en/latest/#restrictions 。
实际上,这些规则很容易遵守。将{% render_block 'css' %}放在标题中,将{% render_block 'js' %}放在base.html文件的结束体标签之前。例如,清单 4-1 中的基本模板现在看起来像清单 4-3 。
Listing 4-3. Minimal base.html file with Sekizai Tags Added
{% load sekizai_tags %}
<!doctype html>
<html>
<head>
<title>{% block title %}Default Title{% endblock title %}</title>
{% render_block 'css' %}
</head>
<body>
{% block content %}{% endblock content %}
{% render_block 'js' %}
</body>
</html>
然后,当你想要添加 CSS 或 JavaScript 文件到你的一个子模板时,你只需要确保addtoblock被包含在块标签中(清单 4-4 )。
Listing 4-4. Basic Child Template With Sekizai Tags
#child.html (fragment)
{% extends "base.html" %}
. . .
{% block "content" %}
{% addtoblock "js" %}
# Add extra scripts here
. . .
{% endaddtoblock %}
{% endblock %}
标记菜单
menus应用实现了四个额外的定制模板标签,用于在 django CMS 中呈现菜单:
show_menushow_menu_below_idshow_sub_menushow_breadcrumb
我们现在最感兴趣的标签是show_menu(我们将在C章节 10 中讨论其余部分)。为了在模板中启用菜单标签,我们使用 Django 的 load 标签:
{% load menu_tags %}
显示菜单
show_menu标签呈现页面的默认导航菜单。菜单的位置取决于模板的设计。在 django CMS 安装程序创建的演示站点中,默认菜单沿页面顶部水平显示,如图 4-3 所示。

图 4-3。
The Default django CMS menu
在这个例子中,我添加了几个页面和一个子页面。请注意,菜单会自动格式化菜单标题并创建子页面的下拉列表;模板引擎创建菜单(在 Bootstrap 的帮助下),不需要您的任何输入。我们稍后将深入探讨 Bootstrap。添加页面将在本书的稍后部分介绍。
show_menu标签有八个可选参数:
from_level。开始呈现菜单的节点级别。默认为"0"(根节点)。to_level。要渲染的节点深度。默认为"100",实际意义上是指所有子节点。extra_inactive。要在当前非活动节点下呈现的节点数。默认值是"0",它有效地隐藏了当前活动菜单项下的所有子节点。extra_active。要在当前活动节点下呈现的节点数。默认值是"100",它有效地展开了当前活动菜单项下的所有子节点。template。如果指定了一个模板(例如"menu.hml"),django CMS 将在您的应用文件夹中呈现文件/templates/menu.html。如果没有指定,django CMS 将呈现默认的menu.html文件(隐藏在 django 的site-packages目录中)。有关这方面的更多信息,请参见附带的注意事项。namespace。模板的名称空间。模板名称空间超出了本书的范围。root_id。菜单根页面的 ID。这在呈现子菜单时使用。next_page。这将检索指定页面 ID 的所有子页面,并将它们呈现在菜单中。
Caution
使用show_menu时,最好总是指定一个模板。Django 的核心理念之一是可移植性,因此所有特定于应用的模板都应该位于该应用的模板目录中。如果您不这样做,对 django CMS 默认模板的更改可能会破坏您的站点。
因为传入位置参数(而不是关键字参数)更容易、更简洁,所以垂直菜单最常见的show_menu形式如下:
{% show_menu 0 100 0 100 "menu.html" %}
这将显示从根开始的整个菜单,非活动子菜单折叠,活动菜单展开。对于水平菜单(如我们的演示应用),它看起来像这样:
{% show_menu 0 1 100 100 "menu.html" %}
这将只显示菜单中的顶级页面,并展开活动菜单项上的子菜单项。
你可能会问自己为什么extra_inactive是100而不是0,因为将它设置为100会展开所有非活动菜单项的子菜单,这是我们不想要的——对吗?
是的,但是我们使用这个技巧来利用 Bootstrap 的一个特性—非活动节点会自动折叠,Bootstrap 会显示下拉箭头图标,这样您就知道父菜单项有子菜单项。如果您将extra_inactive设置为0,您将看不到下拉箭头,除非菜单项处于活动状态。
引导程序
回到第一章,我说过一个现代的网站必须是移动友好的,以迎合现在连接到互联网的众多设备。但是手机友好到底是什么意思呢?
虽然这个问题有许多有时是矛盾的答案,但灵活性是关键:移动设备类型的数量以及它们运行的操作系统多得令人难以置信,一个支持尽可能多的设备的网站需要具有适应性。为了具有灵活性和适应性,站点功能可以归结为三个简单的要求:
- 反应灵敏。这是一个行业术语,但它意味着您的网站将根据设备自动调整大小和重新排列内容。一个设计良好的响应型网站将为使用智能手机的访问者提供与使用 28 英寸显示器的桌面浏览相同的积极用户体验。
- 合规。Android、iOS、OSX、Windows、Linux:他们都有不同的做事方式,不兼容的系统软件,不同的字体和多个浏览器版本。一个移动友好的网站必须能够提供在不同系统上正确呈现的内容。
- 速度。移动数据速度通常较慢,与台式机和笔记本电脑相比,移动设备的处理能力通常较弱。如果你的网站加载速度不快,大多数移动用户会转向竞争对手的网站。
虽然在互联网的服务器端仍然有大量的多样性,但这些需求已经将浏览器端缩减为三种基本技术——CSS、HTML 和 JavaScript。
但是,将这些技术结合起来从头开始构建一个网站是非常困难的,这导致了许多前端 web 框架的出现,这些框架使得使用这些技术的网站的设计、开发和管理变得更加简单。
Bootstrap 最初是两名 Twitter 员工的想法,于 2011 年作为开源技术发布。在此后的四年中,它已经成为前端框架中 800 磅重的大猩猩。Bootstrap 是如此受欢迎,以至于它现在是几乎所有 CMSes 和大型定制站点实现响应式设计的默认框架。
对 Bootstrap 的全面解释超出了本书的范围;然而,对一些关键概念的简单介绍将使设计 django CMS 响应式模板变得容易得多。
自举网格系统
引导网格是一个 12 列、无限行的流体网格系统,可以根据设备自动重新格式化和缩放。网格的确切布局以及它在每个屏幕尺寸上的行为是由预定义的 CSS 类控制的(见下一节)。网格的每个单元格都包含一个 HTML <div>...</div>块,您可以在其中放置任何合法放置在无响应模板的div标记之间的内容。用一个简单的例子来说明这一点更容易。图 4-4 显示了一个带有两栏和右键菜单的简单页面在台式电脑上的样子。

图 4-4。
Responsive template on a desktop computer
在像平板电脑这样的小屏幕上,设计可能看起来像图 4-5 。

图 4-5。
Responsive template on a tablet
在智能手机上,这种设计可能看起来像图 4-6 。

图 4-6。
Responsive template on a smartphone
这是一个非常简单的例子,但是 Bootstrap 足够灵活和强大,可以创建非常复杂的设计,并且不需要任何程序代码。我听到你问,它是怎么做到的?这就是我们接下来要看的——CSS 类和组件。
引导 CSS 类
Bootstrap 用非常复杂的样式表实现了它的格式化魔力,这些样式表定义了 600 多个用于格式化和样式化 HTML 元素的类。这些类别分为八个功能组:
- 网格系统。根据设备大小格式化网格的类别—超小型(
xs)、小型(sm)、中型(md)和大型(lg)—带有列跨越修饰符。例如,col-xs-4类在一个特别小的屏幕(智能手机)上跨越四列。 - 排版。文本样式,如标题、正文、内联文本格式、对齐和特殊格式,如块引号、地址和文本转换。
- 代码。内联和代码块、用户输入和变量格式。
- 桌子。格式和颜色、大小和鼠标交互。
- 表格。表单和表单控件的复杂格式。
- 纽扣。显示选项、颜色和大小。
- 图像。图像大小调整和整形。
- 助手功能。用于上下文着色、clearfix、屏幕阅读器功能以及根据屏幕大小显示和隐藏列的杂项类。
Bootstrap 的 CSS 使用 Less,这是一个 CSS 预处理器,它添加了许多函数,包括变量、混合和编译 CSS 的函数。例子包括:
- 灰度颜色,如,
@gray, @gray-dark, @gray-light。 - 语义色彩,比如
@brand-primary, @brand_info。 - CSS 中颜色变量的使用,比如
background-color: @brand-primary。 - 排印基底,如
@font-family-base, @font-size-base。 - 排版混合,如
@font-size-h1: floor((@font-size-base* 2.6)); - 链接样式,如
@link-color, @link-hover-color
我们将不会在这里进一步探索引导类;我只是想让你在使用 Bootstrap 时体验一下所有有用的设计元素,并帮助你理解当你用 django CMS 构建一个站点设计时,你不必重新发明轮子。要全面了解自举,请参考 http://getbootstrap.com/css/ 。
django CMS 利用了 Bootstrap 的强大功能,因此,django CMS 的默认模板不仅利用了 Bootstrap 类,而且您还可以在自己的模板中轻松实现它们。
引导组件
为了结束我们关于 Bootstrap 的部分,我们只需要简单地谈一谈另一件事——组件。引导组件是可重用的代码,通常是 CSS 和 JavaScript 的混合。django CMS 使用了许多引导组件,包括下拉菜单、导航、提醒和大屏幕。其他组件包括:
- 图像(glyph)
- 按钮组和下拉列表
- 页码
- 面包屑
- 拇指甲
- 进度条
- 面板和井
Note
我们仅仅触及了 Bootstrap 的表面。虽然没有必要更深入地研究 Bootstrap 来理解这本书的其余部分,但是通过书签getbootstrap.com/getting-started/和花几个小时深入理解 Bootstrap 及其功能,你作为一名职业程序员的未来将会受益匪浅。
把这一切联系在一起
我们在这一章已经讲了很多内容,现在是时候把你所学的东西联系起来了。我们将通过检查由 django CMS 安装程序生成的模板文件来做到这一点。
假设您使用了与第二章中的安装示例相同的文件名,您将在中找到这些模板
C:\users\<yourusername>\myCMS-tutorial\mysite\templates\
我们将从清单 4-5 中所示的base.html文件开始(注意:为了提高可读性,一些 URL 被缩短了):
Listing 4-5. Complete sample base.html file
1. {% load cms_tags staticfiles sekizai_tags menu_tags %}
2. <!doctype html>
3. <html>
4. <head>
5. <meta charset="utf-8">
6. <title>
7. {% block title %}
8. This is my new project home page
9. {% endblock title %}
10. </title>
11. <meta name="viewport" content="width=device-width,initial-scale=1">
12. <link rel="stylesheet" href="``https://cdnjs ... bootstrap.min.css
13. <link rel="stylesheet" href="``https:// ... bootstrap-theme.min.css
14. {% render_block "css" %}
15. </head>
16. <body>
17. {% cms_toolbar %}
18. <div class="container">
19. <div class="navbar navbar-default" role="navigation">
20. <div class="navbar-header">
21. <button type="button" class="navbar-toggle" 
data-toggle="collapse" data-target=".navbar-collapse">
22. <span class="sr-only">Toggle navigation</span>
23. <span class="icon-bar"></span>
24. <span class="icon-bar"></span>
25. <span class="icon-bar"></span>
26. </button>
27. <a class="navbar-brand" href="#">Project name</a>
28. </div>
29. <div class="navbar-collapse collapse">
30. <ul class="nav navbar-nav">
31. {% show_menu 0 1 0 100 "menu.html" %}
32. </ul>
33. </div>
34. </div>
35. {% block content %}{% endblock content %}
36. </div>
37. <script src="``https://cdnjs ... jquery.min.js
38. <script src="``https://cdnjs ... bootstrap.min.js
39. {% render_block "js" %}
40. </body>
41\. </html>
现在,您面前已经有了完整的列表,让我们来看一下最重要的部分:
- 一号线。Django 的
load标签接受多个参数,所以我们一次性加载了所有的扩展标签库。 - 第 7 到 9 行。这里 Django 的块标签用于定义页面的标题块。此代码将被定义标题栏的任何子模板覆盖。
- 第 14 行。这是 Sekizai
render_block标记,用于在文件顶部呈现 CSS。 - 第 17 行。这是我们将 django CMS 工具栏加载到页面中的地方。
- 第 19 到 34 行。这是在 Bootstrap 中实现的页面导航栏。为了让导航条显示任何东西,你必须给它传递一个列表,我们在第 31 行用我们的
show_menu标签做了这个。出于好奇,第 21 到 26 行是 Bootstrap 如何呈现小屏幕上显示的“hamburger”图标,而不是完整的菜单。 - 第 35 行。这里 Django 的 block 标签用于定义页面的内容块。这将被定义内容块的任何子模板覆盖。
- 第 39 行。这是 Sekizai
render_block标记,用于在页面底部呈现 JavaScript。使用它是提高页面加载速度的最佳实践。
正如你所看到的,一旦你知道每一行是做什么的,这就很容易理解了。作为练习,我留下了剩下的三个示例模板— page.html, feature.html和menu.html—供您自己检查,以提高您的理解,但这里有一些快速注释可以帮助您:
-
Page.html和feature.html对应 Django 编辑器前端的page和page with feature模板。我们将在下一章深入探讨页面模板。 -
page.html和feature.html都扩展了base.html。 -
You will notice that our sample home page (Figure 2-6) uses the
feature.htmltemplate. The banner at the top is rendered by Bootstrap’sjumbotronclass. Add a new page and select the “page” template, and you will see a blank page template (Figure 4-7).![A978-1-4842-1669-9_4_Fig7_HTML.jpg]()
图 4-7。
The blank
pagetemplate -
注意在
page.html和feature.html中 django CMS 占位符标签的使用。 -
注意
menu.html如何使用 Django 的if/endif和for/endfor标签迭代菜单中列出的所有页面。
摘要
本章到此为止。我们已经非常详细地介绍了模板,现在您应该对如何构建 django CMS 模板有了非常扎实的基础。您还应该熟悉 Bootstrap 的基础知识,以及 django CMS 如何利用 Bootstrap 的 CSS 类来创建一个在大多数设备上都很好看的现代站点模板。
在下一章,我们将继续有趣的东西——设计你自己的模板。
五、你的博客网站:模板
现在您已经对 django CMS 模板的构造有了一个全面的了解,是时候为您的博客网站构建模板了。在本章中,您将:
Start with a fresh, empty install of django CMS. Create your own base.html template. Create a CSS file to apply custom styling to your blog. Create a new template, blogpage.html, that will display a single blog post along with a right sidebar menu listing all posts. Edit your setting file to apply the new templates to your blog site. Note
本章中的所有源代码都可以从该书的网站上下载;但是,建议您第一次通过自己键入文件。有时候这可能会很乏味,但是这样做你肯定会学到更多。
创建全新安装
我们想为我们的博客站点安装一个完全空的 django CMS,所以第一步是创建一个新的虚拟环境(称之为myBlog)并将 django CMS 安装在一个名为myBlogProject的新项目目录中。
创建新安装的步骤与您在第二章中所采取的步骤几乎相同,但是我将简要地一步一步来提醒您(所有命令都是在命令提示符下输入的):
Enter Virtualenv myBlog. Enter myBlog\scripts\activate, and the command prompt should change to (myBlog) C:\Users\YourUsername>. Enter pip install djangocms-installer. Enter mkdir myBlogProject. Enter cd myBlogProject. Enter djangocms -p . myblog. Configuration is almost the same: accept all defaults, except enter en for language and yes to use Bootstrap. This time we don’t was the demo starting page, so we accept the default no for the last question.
我在清单 5-1 中包含了您的命令窗口输出的编辑版本,让您对应该看到的内容有所了解。不会完全一样,但应该很接近。如果一切按计划进行,当您在浏览器中导航到 http://127.0.0.1:8000/ 时,您应该看到 django CMS 登录页面(图 5-1 )。

图 5-1。
A clean install of django CMS Listing 5-1. Command Window Output
Microsoft Windows [Version 10.0.10240]
(c) 2015 Microsoft Corporation. All rights reserved.
C:\Users\Nigel>virtualenv myBlog
Using base prefix 'c:\\python34'
New python executable in myBlog\Scripts\python.exe
Installing setuptools, pip, wheel...done.
C:\Users\Nigel>myBlog\scripts\activate
(myBlog) C:\Users\Nigel>pip install djangocms-installer
Collecting djangocms-installer
Downloading djangocms_installer ... #elipsis = additional text removed
...
Installing collected packages: ...
Successfully installed ...
(myBlog) C:\Users\Nigel>mkdir myBlogProject
(myBlog) C:\Users\Nigel>cd myBlogProject
(myBlog) C:\Users\Nigel\myBlogProject>djangocms -p . myblog
Database configuration (in URL format) [default sqlite://localhost/project.db]:
django CMS version (choices: 2.4, 3.0, 3.1, stable, develop) [default stable]:
Django version (choices: 1.4, 1.5, 1.6, 1.7, 1.8, stable) [default stable]:
Activate Django I18N / L10N setting (choices: yes, no) [default yes]:
Install and configure reversion support (choices: yes, no) [default yes]:
Languages to enable. Option can be provided multiple times, or as a comma separated list. Only language codes supported by Django can be used here: en
Optional default time zone [default Australia/Sydney]:
Activate Django timezone support (choices: yes, no) [default yes]:
Activate CMS permission management (choices: yes, no) [default yes]:
Use Twitter Bootstrap Theme (choices: yes, no) [default no]: yes
Use custom template set [default no]:
Load a starting page with examples after installation (english language only). Choose "no" if you use a custom template set. (choices: yes, no) [default no]: no
Creating the project
Please wait while I install dependencies
...
Dependencies installed
Creating the projectOperations to perform:
...
Synchronizing apps without migrations:
Creating tables...
Installing custom SQL...
Installing indexes...
Running migrations:
...
Creating admin user
Username (leave blank to use 'nigel'):
Email address: <your email>
Password: <enter a password>
Password (again):
Superuser created successfully.
All done!
Get into "C:\Users\Nigel\myBlogProject" directory and type "python manage.py runserver" to start your project
(myBlog) C:\Users\Nigel\myBlogProject>
登录后,您将看到 django CMS 内容创建向导,这是一个简单的自动化工具,用于向您的 django CMS 网站添加内容。目前,我们只有默认的新页面内容向导(图 5-2 )。我们将在第十章中更深入地讨论内容向导。

图 5-2。
The django CMS content creation wizard
继续并选择下一步创建您的新页面。如果需要,输入主页作为页面标题和一些内容。在这个阶段,内容是可选的,因为我们将在本书的稍后部分向该页面添加更多内容。选择屏幕右下角的 Create,刷新你的浏览器,你的站点应该如图 5-3 所示。

图 5-3。
Your new but completely empty website
创建您的基础模板
在这个阶段,你的博客站点看起来很空很无聊,所以是时候建立我们的新模板了。我们将从基础模板开始。为此,我们需要
Rename \myblog\templates\base.html to base.html.old. Create our new base.html file (Listing 5-2) and save it to \myblog\templates\. Create our custom CSS file, myblog.css (Listing 5-3), and save it to \myblog\static\. Create a 50×50 pixel logo and save it to \myblog\static\logo.png. It does not matter what the logo is, but a simple design on a transparent background works best. You can use a program like Microsoft Paint or GIMP to do this (or Photoshop if you have it). I have also included a simple logo in the source code if you don’t want to create your own. Download ie10-viewport-bug-workaround.js `` [1 ] and save it to \myblog\static\. This is a workaround put out by Bootstrap (introduced in Chapter 4) to solve a bug in Internet Explorer on Windows 10. If you are not planning to deploy your website, you don’t have to add this file. Listing 5-2. Our base.html File
{% load cms_tags staticfiles sekizai_tags menu_tags %}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" href="favicon.ico">
<title>{% block title %}MyBlog Title{% endblock title %}</title>
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.4/css/bootstrap.min.css
<!-- MyBlog custom styles -->
<link href="{% static "myblog.css" %}" rel="stylesheet">
<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
<!--[if lt IE 9]>
<script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js
<![endif]-->
{% render_block "css" %}
</head>
<body>
{% cms_toolbar %}
<nav class="navbar navbar-default navbar-static-top">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a href="#"><img src="{% static "logo.png" %}" /></a>
</div>
<div id="navbar" class="collapse navbar-collapse">
<ul class="nav navbar-nav">
{% show_menu 0 1 0 100 "menu.html" %}
</ul>
</div>
</div>
</nav>
<div class="container">
<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>
{% block content %}{% endblock content %}
</div>
<footer class="footer">
<div class="container">
<p class="text-muted">{% block footer %}My Blog©2015{% endblock footer %}</p>
</div>
</footer>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.11.3/jquery.min.js
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.4/js/bootstrap.min.js
<!-- IE10 viewport hack for Surface/desktop Windows 8 bug -->
<script src="{% static "ie10-viewport-bug-workaround.js" %}"></script>
{% render_block "js" %}
</body>
</html>
清单 5-2 中的代码在功能上与上一章中的清单 4-5 相同,因此请参考该讨论以获得更详细的逐行分析。请注意以下更改:
- 我已经将 HTML 头更新为当前的引导头。基本上,这为跨浏览器兼容性增加了一些额外的支持,并为引导脚本增加了不同的内容交付网络(CDN)。您可以从
http://getbootstrap.com/getting-started/#template获得最新的引导模板(您可以将其用作您自己的 django CMS 模板的基础)。 - 我已经将 navbar(顶部菜单)类从
navbar-default改为navbar-static-top以防止 django CMS 工具栏浮动在 navbar 的顶部并遮挡你的顶部菜单。 - 我已经删除了“项目名称”文本锚,并将其替换为一个徽标图像。
- 我在页面内容前添加了一个博客标题。这给了你的网站一个横幅式的标题,这在很多博客上都很常见。
Listing 5-3. The myblog.css File
html {
position: relative;
min-height: 100%;
}
body {
/* Margin bottom by footer height */
margin-bottom: 60px;
font-family: Georgia, "Times New Roman", Times, serif;
color: #555;
}
h1, .h1, h2, .h2, h3, .h3, h4, .h4, h5, .h5,h6, .h6 {
margin-top: 0;
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
font-weight: normal;
color: #333;
}
.footer {
position: absolute;
bottom: 0;
width: 100%;
height: 60px;
background-color: #f5f5f5;
}
.blog-header {
padding-top: 20px;
padding-bottom: 20px;
}
.blog-title {
margin-top: 30px;
margin-bottom: 0;
font-size: 60px;
font-weight: normal;
}
.blog-description {
font-size: 20px;
color: #999;
}
.sidebar-module {
padding: 15px;
margin: 0 -15px 15px;
}
.sidebar-module-inset {
padding: 15px;
background-color: #f5f5f5;
border-radius: 4px;
}
.sidebar-module-inset p:last-child,
.sidebar-module-inset ul:last-child,
.sidebar-module-inset ol:last-child {
margin-bottom: 0;
}
.pager {
margin-bottom: 60px;
text-align: left;
}
.pager > li > a {
width: 140px;
padding: 10px 20px;
text-align: center;
border-radius: 30px;
}
.blog-post {
margin-bottom: 60px;
}
.blog-post-title {
margin-bottom: 5px;
font-size: 40px;
}
.blog-post-meta {
margin-bottom: 20px;
color: #999;
}
body > .container {
padding: 15px 15px 0;
}
.container .text-muted {
margin: 20px 0;
}
.footer > .container {
padding-right: 15px;
padding-left: 15px;
}
. row {
margin-right: 0px!important;
}
清单 5-3 ,myblog.css,是一个标准的 CSS 文件。关于 CSS 的细节已经超出了本书的范围。如果你需要温习你的 CSS 知识,可以在 http://www.w3schools.com/css/ 找到很棒的资源。
如果一切按计划进行,当你重新加载你的主页时,你会看到一个看起来像图 5-4 的网站(注意,我已经折叠了这个截图中的 django CMS 工具栏,这样你就可以看到完整的模板)。

图 5-4。
Your New Blog Base Template
创建您的博客模板
虽然我们的博客看起来比我们开始时漂亮多了,但它看起来仍然不太像一个博客。首先,没有通常的侧边栏列出最近的帖子。其实连帖子都没有!这就是我们现在要做的:清单 5-4 显示了我们博客页面的基本模板page.html。这个页面可以用作许多不同类型的博客页面的基础,而不仅仅是博客文章(例如,列出最新文章的博客卷)。
清单 5-5 显示了我们的博客文章页面blogpage.html,它继承了我们的page.html模板。
您会注意到侧边栏在这些页面中,而不是基本模板中。如果你想知道为什么,那是因为我们的网站有最大的灵活性。我们希望能够显示没有侧边栏的页面(例如,创建全屏阅读页面),或者甚至在某些页面上显示完全不同的侧边栏。以我们的博客为例,这使得以后把它变成一个可重用的应用或 django CMS 插件变得更加容易。
尽可能保持基本模板的通用性几乎总是一件好事。将这一理念与 Django 强大的模板继承能力相结合,随着时间的推移,您会发现您正在收集一个基本模板的组合,它允许您满足最苛刻的设计挑战,而不必每次都从头开始。
Listing 5-4. Our page.html Template
{% extends "base.html" %}
{% load cms_tags sekizai_tags %}
{% block title %}{% page_attribute "page_title" %}{% endblock title %}
{% block content %}
<div class="row">
<div class="col-sm-8 blog-main">
{% block page-inner %}
{% placeholder "content" %}
{% endblock page-inner %}
</div>
<div class="col-sm-3 col-sm-offset-1 blog-sidebar">
<div class="sidebar-module sidebar-module-inset">
<h4>About</h4>
<p>My name is Big Nige and I built this blog all by myself.</p>
</div>
<div class="sidebar-module">
<h4>Latest Posts</h4>
<ol class="list-unstyled">
<li><a href="#">Blogpost 1</a></li>
<li><a href="#">Blogpost 2</a></li>
</ol>
</div>
<div class="sidebar-module">
<h4>User</h4>
<ol class="list-unstyled">
<li><a href="?edit">Log In</a></li>
</ol>
</div>
</div>
</div>
{% endblock content %}
清单 5-4 中的代码应该非常容易理解;需要注意的几件事是:
- 我使用 Bootstrap 的 12 列布局来创建一个 8 列的内容区域,其中有一列偏移,然后是一个 3 列的右侧边栏。
- 我已经提供了一些填充文本,在侧边栏中创建一个虚拟菜单。这是为了让我们可以直观地检查模板。它将被第九章中的占位符代替。
- 我在右侧边栏的底部添加了一个登录链接,使登录变得更容易,而不是每次你想登录时都必须在 URL 上添加
?edit。
Listing 5-5. The blogpage.html Template
{% extends "page.html" %}
{% load cms_tags %}
{% load sekizai_tags %}
{% block title %}{% page_attribute "page_title" %}{% endblock title %}
{% block page-inner %}
<div class="blog-post">
<h2 class="blog-post-title">{% page_attribute "page_title" %}</h2>
<p class="blog-post-meta">Published {{ 
request.current_page.creation_date|date:'d M Y' }} by 
<a href="#">{{ request.current_page.created_by }}</a></p>
{% placeholder "content" %}
{% static_placeholder "social" %}
</div>
{% endblock page-inner %}
感谢 Django 的模板继承,我们的博客文章模板非常简单,因为所有繁重的工作都由base.html和page.html完成了。blogpage.html所做的就是用一篇格式化的博客文章替换{% page-inner %} block 标签,该博客文章显示文章标题、作者和日期信息作为标题,并为社交媒体分享按钮提供一个占位符,我们稍后将在第九章中添加这些按钮。请注意,我们正在访问一些页面属性,这些属性由 django CMS 的标题和页面模型方便地传递给页面上下文。
现在我们终于写好了所有的模板,我们只需要向 django CMS 注册它们。幸运的是,这很容易做到;只需在文本编辑器中打开myblog\setting.py,将CMS_TEMPLATES设置更改为如下:
CMS_TEMPLATES = (
## Customize this
('page.html', 'Page'),
('blogpage.html', 'Blog Page with Sidebar'),
)
保存文件并刷新您的主页。从 django CMS 工具栏中,选择带有侧边栏的页面➤模板➤博客页面,您的模板应该会变成如图 5-5 所示。

图 5-5。
Your completed blog template
就这样!伸个懒腰,拍拍自己的背。这是一个可怕的大量输入(假设你没有作弊和下载文件),但我希望你同意,结果是值得的。
摘要
在这一章中,我们为你的博客网站创建了一套模板;通过这样做,您对 Django 的模板继承以及 Bootstrap 如何使创建响应性页面模板变得容易有了更多的了解。
在下一章,我们将继续为你的网站创建一些页面,我将向你介绍 django CMS 最强大的特性之一:插件。
Footnotes 1
【1】https://github.com/twbs/bootstrap/blob/master/docs/assets/js/ie10-viewport-bug-workaround.js
六、Django CMS 插件
django CMS 灵活性的核心是一个被设计成可插拔的开放结构。从概念上讲,这不同于大多数其他可用的 CMS 软件。对于大多数其他 CMSes,您只能控制作为单个实体(页面或文章)显示在页面上的内容,并且内容通常是从管理后端编辑的。
django CMS 采取了一种不同的方法——它的插件架构提供了灵活的嵌入式容器,可以直接从前端编辑。这些容器旨在方便地包含所有形式的内容,从简单的 HTML 标签到复杂的嵌入式应用。
django CMS 不限制页面布局;例如,你可以将一个横幅放在页面顶部,写一篇文章放在它下面,然后在文章下面放一个社交媒体插件。您可以自由地将这种布局复制到其他页面,或者在每个页面上做一些完全不同的事情。我们将在第八章中讨论这样做的步骤。然而,在接下来的两章中,我们将首先探索您已经拥有的所有插件。在这一章中,你将学习内置的 django CMS 插件是如何工作的。
入门指南
理解这是如何工作的最好方法是直接投入进去。点击你在上一章创建的主页,然后点击 django CMS 工具栏中间的结构按钮。你的屏幕应该看起来如图 6-1 所示。

图 6-1。
An empty template in structural view
页面上的内容栏和社交栏与模板中同名的占位符相对应。这些是容器,您可以在其中放置任何想要添加到页面的插件。例如,我们的内容向导已经向内容占位符添加了一个文本插件。如果你查看底层的 HTML 代码(通过选择 View Source ),你会发现它们实际上只是 HTML divs。
每个容器的右侧都有一个上下文菜单。如果您点击加号(+)图标,屏幕中央将出现一个弹出覆盖图(图 6-2 )。列表中的每一项都是一个插件。在本章的剩余部分,我们将依次看看这些插件,你将学会如何使用它们为你的网站创建不同种类的内容。

图 6-2。
A placeholder context menu
默认插件
django CMS 安装了 11 个默认插件;它们共同提供了显示和格式化常见 web 内容(如文本、视频和音频、图像和文件)所需的所有基本功能。django CMS 项目团队和第三方提供了更多的 django CMS 插件,您可以通过复制和增强其中一个默认插件,或者从头开始构建自己的插件,轻松添加自己的定制插件。我们将在下一章讨论第三方插件,并在第八章中构建你自己的定制插件,但首先让我们更详细地看看默认插件。
Note
如果你已经使用了 django CMS 的早期版本,请注意占位符和插件不再从管理后端管理;现在,必须从结构视图的前端对它们进行管理。
安装默认插件
如果你已经遵循了第二章中的安装说明,这一步是不必要的,但是,如果你必须重新安装,或者想在自定义站点上使用它,了解如何安装默认插件是值得的。
安装一个默认插件非常简单;只需执行以下操作:
Install the plugin using pip. Add it to your INSTALLED_APPS in settings.py.
例如,您可以安装带有pip install django-cms-file的文件插件,并将'djangocms_file',添加到您的INSTALLED_APPS中,以便在您的应用中可用。
有关单独安装所有默认插件的说明,请参见 http://www.django-cms.org/en/addons/ 。
文本插件
如果你曾经使用过在线的、基于浏览器的文本编辑器,你会对这个文本插件很熟悉。如果您还没有,不要担心,因为它非常简单,工作起来就像一个简化的文字处理器。你会经常使用文本插件,肯定会比系统中的其他插件更多,所以真正理解它的工作原理是值得的。从下拉菜单中选择文本插件,一个如图 6-3 所示的窗口将会弹出到您的屏幕上。

图 6-3。
The django CMS Text plugin
与文字处理器或高级 HTML 编辑器相比,编辑器的功能似乎很基本,但在网页内容创作中,越多不一定越好。表 6-1 列出了基本编辑器的每个功能。
表 6-1。
Django CMS Text Plugin Toolbar Functions
| 图标 | 功能 | | --- | --- | |  | 退回/重做 | |  | 插入文件/链接/图片或视频。这些插件的行为与直接在页面上使用时完全一样。 | |  | 显示区块。在页面上显示 HTML 块的虚线轮廓。用于可视化布局和检测空 HTML 标签。 | |  | 段落格式下拉列表。选项包括标题、普通文本和其他格式。 | |  | 应用特殊的文本样式,如代码格式、删除的文本和引号。 | |  | 选择文本前景色和背景色。 | |  | 粘贴纯文本和从 Word 粘贴。后者清除微软工作格式化标签。 | |  | 文本格式:粗体、斜体、下划线、下标和上标。 | |  | 清除所选文本的格式。 | |  | 文本对齐方式:左对齐、居中对齐或右对齐。 | |  | 插入一条水平线。 | |  | 列表。编号,子弹。列表缩进和突出。 | |  | 插入表格。这将打开另一个窗口,您可以在其中输入行、列和表格的宽度和高度信息。 | |  | 直接编辑 HTML 源代码。 |文本插件有一些限制——没有所见即所得的表格或嵌入插件(图像、文件和视频)的大小调整,任何高级 HTML 都需要直接编辑源代码。
实际上,这些问题并没有你想象的那么大。
对于初学者来说,在表中使用固定宽度的列几乎总是一件坏事,因为它们在小屏幕上不能正常缩放和流动;你永远不应该用表格来布局。通过切换到内容视图可以快速预览媒体文件,插件系统使布局变得非常简单。
要理解的最重要的概念是,你不需要用一个单独的文本插件来布局整个页面。这可能是刚接触 django CMS 的人犯的第一个错误;尤其是如果他们过去使用过其他的 CMSes。让我通过扩展我在本章开始时介绍的快速示例来说明。假设你有一个相当标准的页面:横幅在顶部,接下来是一些介绍性的文本,一个图像浮动在左侧或右侧,还有一些文本浮动在图像旁边并继续在下面。通常在这种情况下,是图像元素和横幅让页面作者摆弄 HTML 以使一切看起来正确。
在 django CMS 中,你可以在横幅上放一个图片插件,然后放一个介绍文字插件。在这下面,你可以使用一个多栏插件,拆分百分比宽度以适应图像,将图像放在一栏,文章文本放在另一栏。然后你用下面的另一个文本插件完成,它包含了文章的其余部分(这个例子中提到的附加插件将很快被完整解释)。
注意,这不是一个很好的例子;通常情况下,你不应该有任何问题的文字流动周围的图像为主要文章,所以你不会去这样一个精心布局,但它真的很重要的是要明白,你有这种灵活性,如果你有更高的布局要求。
最后,没有什么可以阻止你使用一个外部的 HTML 编辑器,将源代码直接粘贴到文本插件中。“从 Word 粘贴”按钮甚至允许您将 Word 用作 HTML 编辑器(但请不要这样做)。
链接插件
链接插件(图 6-4 )将链接插入页面内容。它也可以用来在文本插件和多栏插件中插入链接。有五种可用的链接类型—链接(URL)、链接到网站上的页面、链接到锚、电子邮件链接和电话链接。

图 6-4。
The Link plugin Note
如果您输入多个链接,链接插件不会抛出错误,所以请确保您只填写了一个链接字段。
关于链接插件,有一些事情需要注意:
- 当您在链接字段中输入 URL 时,它必须带有
http://或http://前缀,原始 URL 会导致错误。 - 您需要自己在页面中创建锚点,方法是选择 Edit Source 并输入
<a name="anchor_name" />(用您的锚点名称替换anchor_name)。然后将锚点字段链接到您的锚点名称。有一个针对文本插件的黑客可以解决这个问题,但对于书中的这一点来说有点超前。我已经将它包含在附带的侧边栏中。 - 电话链接将插入一个
tel://...链接到您的页面。根据您电脑或平板电脑上的软件,这可能会启动另一个应用。在智能手机上,它会简单地拨打电话号码。
Adding “Insert Anchor” to the text plugin
在源代码中添加锚点非常简单,适合大多数内容创建工作;然而,如果你发现你在你的页面中输入了很多锚点,那么在文本插件中添加它们的工具将会非常有用。
幸运的是,文本插件工具栏是基于一个名为 CKEditor 的 JavaScript HTML 编辑器。CKEditor 真正酷的地方是它已经有了一个插入锚点工具,我们要做的就是启用它。
打开您的settings.py,并将其添加到文件底部:
CKEDITOR_SETTINGS = {
'toolbar':[
['Undo', 'Redo'],
['cmsplugins', '-', 'ShowBlocks'],
['Format', 'Styles'],
['TextColor', 'BGColor', '-', 'PasteText', 'PasteFromWord'],
['Maximize', ''],
'/',
['Bold', 'Italic', 'Underline', '-', 'Subscript', 'Superscript', '-', 'RemoveFormat'],
['JustifyLeft', 'JustifyCenter', 'JustifyRight'],
['HorizontalRule'],
['Anchor'],
['NumberedList', 'BulletedList', '-', 'Outdent', 'Indent', '-', 'Table'],
['Source']
],
}
重新加载您的页面(您可能需要清空浏览器缓存并重启开发服务器),您将在水平标尺按钮旁边看到一个漂亮的标志图标(也称为插入锚点工具)。
如果你喜欢冒险,你还可以做很多其他的事情来修改编辑器,但是一定要先备份你的文件!
图片插件
图片插件(图 6-5 )将图片插入你的页面。它也可以在文本插件和多栏插件中使用。图片插件不允许上传时调整图像大小,也不做任何自动缩略图转换;因此,在你上传之前,你的图片大小合适是很重要的。

图 6-5。
The Picture plugin Tip
要创建一个缩略图,您可以点击它来显示全尺寸图像,将全尺寸图像保存到myBlogProject\media\,然后将链接:缩略图上的文本设置为"../media/<full size image filename>。我们稍后将安装一个插件,它可以帮助简化这个过程,但首先它有助于了解如何用默认设置实现这个结果。
文件插件
文件插件(图 6-6 )将文件插入你的页面。像图片插件一样,它也可以用在文本和多栏插件中。这是一个非常简单的工具——你只需要选择要上传的文件,并选择一个标题(这将被用作你的锚文本)。

图 6-6。
The File plugin
文件插件只提供最基本的文件嵌入功能。对于您将定期嵌入文件的更复杂的站点,建议您安装并使用 Django-Filer 插件,这将在下一章中介绍。
视频插件
视频插件(图 6-7 )将视频嵌入你的页面。它也可以在文本和多列插件中使用。嵌入的视频可以是您网站上的文件,也可以是指向外部网站(如 YouTube 或 Vimeo)上的视频的嵌入链接。使用视频插件时,请记住以下几点:

图 6-7。
The Video plugin
- 如果你想嵌入你自己的视频,你可能不得不使用编码来得到你想要的结果。一般来说,任何常见的视频容器(。avi,. mp4,. m4v,.mkv)将在使用 H.264 编解码器的情况下工作。如果遇到问题,网上有大量关于如何转码视频文件的信息。
- 宽度和高度是必填字段。如果您使用预览图像,请将这些设置为图像尺寸;如果您链接到外部视频,最好保持与原始视频相同的宽高比,例如 4:3 视频的宽高比为 400。
- 视频插件配置屏幕底部的“显示颜色”选项卡允许您为嵌入的视频自定义一系列颜色设置。
Tip
如果您想将自定义设置(包括颜色设置)应用到您网站上的所有视频,可以将它们添加到您的settings.py文件中。可用的设置如下:
VIDEO_AUTOPLAY ((default: False)
VIDEO_AUTOHIDE (default: False)
VIDEO_FULLSCREEN (default: True)
VIDEO_LOOP (default: False)
VIDEO_AUTOPLAY (default: False)
VIDEO_BG_COLOR (default: "000000")
VIDEO_TEXT_COLOR (default: "FFFFFF")
VIDEO_SEEKBAR_COLOR (default: "13ABEC")
VIDEO_SEEKBARBG_COLOR (default: "333333")
VIDEO_LOADINGBAR_COLOR (default: "828282")
VIDEO_BUTTON_OUT_COLOR (default: "333333")
VIDEO_BUTTON_OVER_COLOR (default: "000000")
VIDEO_BUTTON_HIGHLIGHT_COLOR (default: "FFFFFF")
多列插件
多列插件(图 6-8 )允许你以列的形式格式化你的页面内容。它不仅对多列文本有用;它是任何其他默认 django CMS 插件以及兼容的第三方和自定义插件的容器。你甚至可以嵌套多列插件。

图 6-8。
Multi Columns plugin
使用多列插件非常简单——选择你想要的列数和默认的列宽。这两种设置以后都可以很容易地更改。
样式插件
样式插件(图 6-9 )允许你为放置在其中的页面元素添加自定义样式。例如,如果您想要将自定义样式应用到文本插件,您可以将文本插件放在样式插件中。

图 6-9。
The Style plugin
使用样式插件很简单;只需从列表中选择一个类名。这将把类名应用到 HTML div。然后在自定义 CSS 文件中设置样式格式。例如,如果您选择了info类,它将应用 CSS 文件中.info类的样式。
默认类没有什么特别的;通过修改您的settings.py文件,您可以添加更多的类或者完全替换它们。例如,要在下拉列表中添加一个新的类mystyle,请在设置中添加以下内容:
CMS_STYLE_NAMES = (
('info', ("info")),
('new', ("new")),
('hint', ("hint")),
('mystyle', ("mystyle")),
)
还有许多高级设置可以添加到样式插件中,包括:
- 使用 HTML 5 文章或章节标签代替默认的 div 标签
- 应用附加类
- 设置填充和边距
Tip
您可以将引导程序类添加到附加类列表中。如果你想应用 Bootstrap 上下文类(比如。warning,或。danger)到内容。
预告插件
预告插件(图 6-10 )显示一个图像,上面有一个标题,下面有一个纯文本块。它最好用在多列标签中,使它在页面文本中左右浮动,但是像 django CMS 中的其他东西一样,它的用途只受你的想象力的限制。

图 6-10。
The Teaser plugin
因为描述是纯文本,并且将呈现与你的正文相同的内容,所以将你的预告插件封装在一个样式插件中,以对预告应用自定义样式也是值得的。
Flash 插件
Flash 插件(图 6-11 )是另一个非常简单的插件——只需选择你的 Flash (swf)文件并指定宽度和高度。

图 6-11。
The Flash plugin Warning
因为我们正在做一个手机友好的网站,应该注意到 Flash 文件在几个平台上有很多兼容性问题。一般的建议是不要使用 Flash,除非你有非常好的理由这样做。
谷歌地图插件
谷歌地图插件(图 6-12 )在你的页面中嵌入了谷歌地图。设置很简单;但是,有几件事需要注意:

图 6-12。
The Google Map plugin
- 在美国之外,通过在 City:字段中输入
<city>, <state/province>, <country>,您将更有可能显示正确的地图参考。 - 纬度和经度设置不是直接的地图参考;它们用于微调地图图钉的确切位置。
创建别名插件
创建别名插件为所选插件创建一个别名,这允许它在你的网站的任何页面上使用,并且对别名插件的一个实例的任何更新将自动应用到所有其他实例。它不是被设计成单独使用的,而是作为一种将插件复制到你的站点的多个页面上的方式,并且当插件内容改变时,插件内容会自动更新。图 6-13a 和 6-13b 说明了别名过程。

图 6-13(b)。
Adding the aliased plugin to a page

图 6-13(a)。
Copying a plugin with Create Alias
在图 6-13a 中,我已经使用 Create Alias 为页面上的文本插件创建了一个别名。
创建插件的链接副本就像将别名粘贴到页面上的占位符或插件中一样简单,如图 6-13b 所示。请注意,出于演示的目的,我粘贴到了同一页面上;在一个真实的网站中,你可以把它粘贴到另一个页面上。
摘要
在这一章中,我们简要地看了 django CMS 中内置插件提供的功能。我们将在第八章中使用这些插件。
在下一章,我们将通过添加一些其他开发者为 django CMS 开发的优秀插件来增加基本插件的功能。
七、高级插件
在前一章中,我们介绍了 django CMS 预装的所有默认插件。对于内容不经常变化的简单网站,这些对于创建和管理网站来说已经足够了。
然而,一旦你有了一个内容更复杂的网站,并且需要更经常地发布和更新内容,有许多第三方插件可以让你更容易地在 django CMS 网站上创建和管理内容。
本章介绍了一些扩展和增强 django CMS 插件功能的第三方应用。在下一章中,我们将开始使用它们来为你的博客站点构建内容。
简易缩略图
如果您还记得上一章,为了用默认的图像插件创建缩略图,您必须手动调整源图像的大小来创建缩略图,然后链接到源图像以获得全分辨率视图。
因为这是 CMS 中非常常见的任务,所以已经开发了许多用于创建缩略图的应用;轻松缩略图就是这样一个应用。最初是为 Django 创建的,Easy Thumbnails 也可以很好地与 django CMS 配合使用。它是为动态创建缩略图而设计的——根据一个简单的模板,为您放在页面中的图像自动创建缩略图。
Note
简易缩略图最适合不需要复杂媒体处理的小型网站。如果你的网站更复杂,你最好使用 CMSplugin-filer,它有简单的缩略图。CMSplugin filer 的最新版本可以从 https://github.com/stefanfoulis/cmsplugin-filer 下载。
要使用简易缩略图,您必须首先使用pip安装它:
$ pip install easy-thumbnails
一旦安装了简易缩略图,我们需要将它添加到我们的项目中。首先,将它添加到您在settings.py中安装的应用中:
INSTALLED_APPS = (
...
'easy_thumbnails',
)
然后运行migrate命令将必要的表添加到您的项目中:
$ python manage.py migrate easy_thumbnails
一旦 Easy Thumbnails 安装到您的项目中,它就需要一个模板文件来正确地调整图像大小并创建缩略图文件。清单 7-1 中显示了一个简单的模板文件。要在您的项目中启用模板,请将文件命名为picture.html,并将其保存到\myBlog\templates\cms\plugins。(你需要在你的templates目录下创建新的文件夹。)
Listing 7-1. The Easy Thumbnails Template File (picture.html)
{% load thumbnail %}
{% if link %}<a href="{{ link }}">{% endif %}
{% if placeholder == "content" %}
<img src="{% thumbnail picture.image 300x600 %}"
{% if picture.alt %} alt="{{ picture.alt }}"{% endif %}
{% if picture.longdesc %} title="{{ picture.longdesc }}"{% endif %} />
{% else %}
{% if placeholder == "authorbio" %}
<img src="{% thumbnail picture.image 50x50 crop %}"
{% if picture.alt %} alt="{{ picture.alt }}"{% endif %}
{% if picture.longdesc %} title="{{ picture.longdesc }}"{% endif %} />
{% endif %}
{% endif %}
{% if link %}</a>{% endif %}
这个模板非常简单。要查看它在做什么,让我们来看一下代码:
- 我们首先需要用
{% load thumbnail %}将自定义缩略图标签加载到模板中。 - 外部的
if/else语句根据 django CMS 页面模板中的占位符选择正确的缩略图大小。我们在第二章的中创建了content占位符。注意,为了实际工作,您需要修改您的基础(或子模板)来包含authorbio占位符。 - 缩略图创建魔术由
{% thumbnail picture.image ... %}标签执行。它设置缩略图的大小,在作者头像的情况下,裁剪图像。 - 如果有链接附加到图像,附加的
if/else标签创建一个锚点,如果这些元素存在,为图像创建alt和title标签。
关于配置简易缩略图的最后一点说明。如果你打算重复使用你的应用,或者想要保持整个网站的一致性和灵活性,使用别名比硬编码缩略图大小更好,例如,通过将以下内容添加到你的settings.py:
THUMBNAIL_ALIASES = {
'': {
'avatar': {'size': (50, 50), 'crop': True},
},
}
还要修改您的模板,以便:
<img src="{% thumbnail picture.image 50x50 crop %}"
变成了这样:
<img src="{% thumbnail picture.image avatar %}"
现在,您可以自由地将模板复制到多个项目,并为所有使用avatar别名的模板设置图像参数,而无需修改多个文件。
这只是对简易缩略图的简单介绍;有关所有相关配置选项和设置的完整描述和详细信息,请参考简易缩略图文档 1 。
CMSplugin 文件
CMSplugin-filer 将 Django 的文件管理器 Django-filer 添加到 django CMS 中。它提供了许多您期望从文件管理应用中获得的功能:
- 创建、重命名和删除文件夹。
- 上传、重命名和删除任何类型的文件(尽管您很可能只管理常见的媒体文件,如图像、视频、PDF 和文档文件。
- 整理服务器上的媒体文件。
- 应用文件权限和安全下载(编写本文时的实验特性)。
要安装 CMSplugin-filer,我们首先用pip安装应用文件:
pip install cmsplugin-filer
为了确保 CMSplugin-filer 安装正确,我们必须首先将 Django-filer 添加到我们的项目中。将以下内容添加到您的settings.py:
INSTALLED_APPS = (
. . .
'filer',
'easy_thumbnails',
)
然后,您需要将应用表安装到项目中。为此,运行两个命令:
python manage.py makemigrations
python manage.py migrate
第一个命令确保我们所有的迁移同步,第二个命令执行实际的迁移。现在是安装 CMSplugin-filer 应用文件的时候了。首先,我们必须对settings.py进行一些更改:
INSTALLED_APPS = (
. . .
'cmsplugin_filer_file',
'cmsplugin_filer_folder',
'cmsplugin_filer_link',
'cmsplugin_filer_image',
'cmsplugin_filer_teaser',
'cmsplugin_filer_video',
)
. . .
MIGRATION_MODULES = {
. . .
'cmsplugin_filer_file': 'cmsplugin_filer_file.migrations_django',
'cmsplugin_filer_folder': 'cmsplugin_filer_folder.migrations_django',
'cmsplugin_filer_link': 'cmsplugin_filer_link.migrations_django',
'cmsplugin_filer_image': 'cmsplugin_filer_image.migrations_django',
'cmsplugin_filer_teaser': 'cmsplugin_filer_teaser.migrations_django',
'cmsplugin_filer_video': 'cmsplugin_filer_video.migrations_django'
}
然后我们只需要再次运行migrate来确保我们已经将所有必要的表添加到项目中:
python manage.py migrate
如果安装成功,您将有六个新的插件选项添加到您的页面结构编辑器中(图 7-1 ):
- 文件*
- 文件夹
- 图像*
- 链接*
- 戏弄者
- 视频*

图 7-1。
Plugins added by CMSplugin-filer
*这些插件也被添加到文本插件中。
顺便说一下,一旦你安装了 CMSplugin-filer,你就不太可能再使用相应的默认插件了。为了减少插件下拉列表中的选项数量,你只需要删除重复的选项。您可以通过注释掉您的settings.py中的重复项来轻松做到这一点:
INSTALLED_APPS = (
. . .
'djangocms_column',
#'djangocms_file',
'djangocms_flash',
'djangocms_googlemap',
'djangocms_inherit',
#'djangocms_link',
#'djangocms_picture',
#'djangocms_teaser',
#'djangocms_video',
. . .
)
我们将在下一章的实际例子中使用每个文件管理器插件。为了便于参考,下面提供了每个插件的介绍。我们将从文件管理器开始,它是所有插件共有的,然后依次讨论每个插件。
文件管理器
所有六个新的 CMSplugin-filer 插件的共同点是文件管理器(图 7-2 )。通过点击搜索图标(
)从每个插件中打开文件管理器。要选择一个文件,单击您想要插入的文件旁边的选择图标(
)。

图 7-2。
The CMSplugin-filer file manager
使用文件管理器,您有以下选择:
- 新文件夹。在选定文件夹下添加新文件夹。在本例中,我添加了一个名为
siteimages的新文件夹。 - 上传。允许您将新文件从您的计算机上传到选定的文件夹。当您第一次上传文件时,它会被添加到屏幕右侧的剪贴板中,您可以将它添加到当前目录中,如果您改变主意,也可以放弃上传。
- 搜索。在所有文件夹中搜索文件。
- 改变。允许您更改文件属性和元数据。可用选项取决于上传的文件类型。当我们查看单个插件时,您将了解更多关于更改选项的信息。
Note
CMSplugin-filer 安装了完整的 Django-filer 应用,它提供了一个有效的媒体管理器,不仅可以从前端(如这些示例中所示)访问,还可以通过管理后端访问。我们将在下一章讨论更多的管理后端。
文件插件
filer 文件插件很简单(图 7-3);只需输入您的标题(这将成为文件锚文本)和您想要嵌入的文件。

图 7-3。
The CMSplugin-filer File plugin
文件夹插件
文件夹插件(图 7-4 )将文件夹的内容呈现为项目符号列表或幻灯片。它对于创建图像幻灯片非常有用;然而,它也是一个在网页上列出目录内容的方便工具。

图 7-4。
The Folder plugin
文件夹插件的配置很简单;只需为插件输入一个标题,并选择您希望附加的文件夹。如果您选择“列表”风格,文件夹中的每个文件将作为链接到您的文件的锚列在您的页面上,如果您选择“幻灯片”风格,文件夹中的所有图像将显示为幻灯片。
图像插件
CMSplugin-filer 中的图片插件(图 7-5 )对基本图片插件进行了大量增强。可以通过文件管理器添加图像,也可以使用备选图像 URL 字段直接链接图像。您还可以添加标题以及常用的替代文本。

图 7-5。
The Image plugin
图像插件还提供图像缩放选项和高级链接(图 7-6 )。图像缩放和链接选项非常简单。需要注意的事项:

图 7-6。
Additional options for the Image plugin
- 使用原始图像。这将覆盖所有其他设置,并且只显示图像而不调整大小。
- 宽度/高度。您可以指定宽度或高度来获得成比例的大小,但是要进行裁剪,您必须同时指定两者。
- 高档。简单地调整图像大小,无需任何重采样。请注意,如果放大,小图像的质量可能会很低。
- 缩略图选项。允许应用预定义的缩略图大小设置。单击绿色加号(+)添加新设置。您添加的任何新设置将适用于所有图像。
- 使用自动缩放。允许图像插件尝试根据上下文缩放图像。请注意,根据图像所在的占位符,图像的缩放比例会有所不同。
- 图像对齐。不对图像应用任何样式,只是一个 HTML 类。您可以在一个定制的 CSS 文件中提供样式(在我们的例子中是
blog.css)。 - 链接原始图像。打开全尺寸图像。
- 描述。django CMS 将把你放在这个字段中的任何内容作为文本呈现在一个
span标签中。应用样式由您决定(参见随附的注释)。
Note
图像标题和描述是以 HTML span标签的形式添加的,因此它们将与图像内联呈现,而不是像您所期望的那样位于图像下方。幸运的是,这很容易解决。django CMS 将类应用于图像标题和描述(分别是title和desc)。将这些类添加到您的blog.css文件中,以在图像下方显示标题和描述:
.title, .desc {
display: block;
}
链接插件
CMSplugin-filer 链接插件(图 7-7 )与基本链接插件非常相似,唯一的主要区别是增加了文件管理器。名称字段是锚文本,您可以选择直接链接(URL)、页面、邮件和文件链接。与基本版本一样,如果您填写多个链接字段,这个链接插件不会抛出错误,因此请确保您只在您想要的字段中输入信息。

图 7-7。
The Link plugin
预告插件
CMSplugin-filer 中的 Teaser 插件(图 7-8 )的功能也与其基本版本非常相似,只是在“更多”链接下增加了文件管理器和图像大小调整选项。

图 7-8。
The Teaser plugin Note
标题呈现为 HTML H2标签,描述呈现为基本段落(p标签),没有默认的 HTML 类,所以建议将 CMSplugin-filer Teaser 插件放在 Style 插件中,就像基本版本一样。
视频插件
视频插件的 CMSplugin-filer 版本(图 7-9 )与基本版本相同,除了增加了文件管理器和默认大小 320×240。

图 7-9。
The Video plugin
djangocms-表单
djangocms-forms 是由 Mishbah Razzaque 创建的 djangocms 的第三方表单插件。它提供了你需要的所有表单域,以及添加 CAPTCHA 来过滤垃圾邮件和在数据库中保存表单提交的能力;所有这些都不需要编写一行代码。要在我们的项目中使用 djangocms-forms,首先我们需要安装它:
pip install djangocms- forms
然后我们需要把djangocms_forms加到INSTALLED_APPS上:
INSTALLED_APPS = (
...
'djangocms_forms',
...
)
最后,我们同步数据库:
python manage.py migrate
Tip
到目前为止,我们已经一次安装了一个插件。这可能是一个很好的时机来注意所有你希望包含在你的网站中的插件(和应用)可以使用一个需求文件一次安装。因为需求文件是 pip 的一个特性,而不是 django CMS 的,所以我不会在这里深入讨论,但是如果你有兴趣,可以看看 https://pip.readthedocs.org/en/1.1/requirements.html 。
为了在我们的应用中使用 djangocms-forms 插件,我们需要将它挂接到我们的项目中。首先,我们需要将表单 URL 添加到项目中。打开\myblog\urls.py并将以下内容添加到您的urlpatterns中:
urlpatterns = patterns(
...
url(r'^', include('djangocms_forms.urls')),
...
)
然后,你应该能够通过进入➤高级设置➤应用页面并从下拉列表中选择表单,将表单插件挂入你的页面。如果表单选项没有出现在下拉列表中,您可能需要重新启动开发服务器。
保存页面设置,现在当你编辑你的页面时,你将会看到通用下的表单选项。选择插件,你应该会看到一个类似图 7-10 的弹出窗口。

图 7-10。
The Djangocms-forms plugin (partial)
不要被所有可能的选择吓倒;创建一个详细的表单实际上非常容易,但是首先我们必须注意一件事。
因为我们正在开发中,我们没有设置我们的电子邮件,所以我们不能测试表单。幸运的是,Django 提供了一个基于文件的电子邮件后端,专门用于帮助开发人员测试电子邮件,而无需首先配置电子邮件服务器。要让我们的电子邮件后端运行,请在您的settings.py末尾添加以下内容:
EMAIL_BACKEND = 'django.core.mail.backends.filebased.EmailBackend'
EMAIL_FILE_PATH = '/Users/<your username>/maildump'
您不需要创建maildump文件夹;Django 会在你第一次尝试发送电子邮件时帮你完成。当你尝试发送电子邮件时,你会发现这个文件夹中包含一些名为20151009-100625-98201520.log的文件。在这个日志文件中是您的完整消息,包括所有邮件头和错误消息。非常便于测试。
创建表单
图 7-10 显示了创建表单时弹出窗口的局部视图。配置屏幕很长,但所有字段都很简单:
- 表单名称。表单名称将显示在您网站的管理后端,这样您就可以知道提交了哪个表单。下一节将详细介绍表单管理。
- 标题。这是将在您的页面中显示的标题。
- 描述。这将显示在您页面的标题下。您可以在这里使用 HTML 标签来格式化您的代码。
- 提交按钮文本。默认为“提交”,但您可以更改。
- 发布提交消息。用户提交表单后将在页面上显示的消息。您可以在这里使用 HTML 标签来格式化您的代码。提示:在这里使用 Bootstrap 类
alert alert-success来获得一个非常格式化的成功框。 - 重定向?如果您希望在提交表单后重定向用户,请选择一个目标。
- 提交设置。设置收件人、发件人和电子邮件主题。还允许您设置验证码。参见
https://github.com/mishbahr/djangocms-forms了解更多关于在 djangocms-forms 中使用验证码的信息。
添加表单域
添加表单字段非常简单,只需单击表单创建弹出窗口底部的绿色加号(+)图标。这将扩展窗口,显示类似于图 7-11 的配置屏幕。

图 7-11。
Adding form fields
字段编辑器有以下选项:
- 名字。将显示在表单中字段的左侧。
- 字段类型。字段的数据类型。可用选项包括:
- 文本、文本区域、电子邮件、号码、电话、URL、复选框、多选框、下拉列表、单选、文件上传、日期、时间、密码和隐藏。
- Djangocms-form 为所有相关字段(如电子邮件和号码)提供自动验证。如果所有标记为“必填”的字段为空,也会引发错误。
- 默认值。设置预填充值。请注意,这将覆盖您在占位符文本中输入的任何内容。
- 占位符文本。字段中的灰色提示文本。在大多数现代 web 表单中,这是用来代替工具提示的。
- 描述。将出现在字段正下方的字段的简短描述。
表单管理
配置表单时选择“保存到数据库”会将所有表单域保存到您的项目数据库中。如果您导航到根(example.com)管理,从侧边栏中选择表单提交,并扩展到全屏,您将看到一个类似图 7-12 的窗口。

图 7-12。
Form Submissions in the Admin tool
“表单提交”窗口允许您删除提交的表单,以及将所有提交的表单导出到外部文件。可用的格式有 CSV、JSON、YAML 和 Microsoft Excel。对于导出表单数据用于外部程序,甚至导入邮件列表管理器非常有用。
摘要
本章我们只讨论了三个插件,Easy Thumbnails,CMSplugin-filer 和 Djangocms-forms;django CMS 有这么多可用的插件,每周都有更多的插件被添加进来,以至于没有足够的空间来涵盖它们。
如果你想自己探索 django CMS 可用的全部插件,一个好的起点是 django CMS 项目网站: http://www.django-cms.org/en/addons/ .
在下一章中,我们将把这三个插件,连同第六章的基本插件一起,很好地用于为我们的站点创建一些内容。
Footnotes 1
http://easy-thumbnails.readthedocs.org/en/2.1/
八、在 django CMS 中创作
在前七章中,我们着重于设计我们的网站模板和探索 django CMS 的功能。在这一章中,我们将会把我们所学到的应用到实践中,为你的观众创造你的网站中最重要的部分:内容。
凭借前端编辑和灵活的插件架构,django CMS 为管理员和网站内容创建者提供了强大的内容格式化和编辑功能。
本章首先概述了 django CMS 工具栏及其功能。然后,我们将使用 django CMS 的内置插件,以及我们在上一章探讨的第三方插件,为您的网站创建三个页面——主页、关于页面和联系页面。一旦你的博客应用开始运行,我们还会为你创建一些博客文章,供你在后面的章节中使用。
在本章的后面,我们将详细探讨网站管理;特别是,我们将深入挖掘 Django 的auth.user模型,并将设置用户组和权限,这样我们的网站就像一个专业的 CMS——拥有适当的用户、作者、编辑和管理员角色以及仅限会员的内容。
django CMS 工具栏
django CMS 工具栏提供了对站点创作中所有重要功能的访问。
网站根目录(example.com)
网站的根菜单(图 8-1 )提供了页面和用户管理的快速链接,以及完整管理后端的链接。如果您没有在管理界面中更改默认的站点描述,它将被称为example.com。我将在本章的后面告诉你如何改变这一点。

图 8-1。
The django CMS root menu
这些菜单选项仅对拥有完全管理权限的用户可用。我们将在本章后面介绍管理功能。根菜单还允许任何注册用户(不仅仅是管理员)修改用户设置,包括管理界面中的默认语言,以及禁用工具栏。后者对于预览没有工具栏的网站很有用。
根菜单还提供对 django CMS 剪贴板的访问,剪贴板将包含最新复制的插件或最后创建的插件别名。
Tip
要重新启用工具栏,请返回编辑模式(/?edit)。
页
页面菜单(图 8-2 )提供对 django CMS 中所有页面管理功能的访问。

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

图 8-3。
Adding new pages
django CMS 提供了开箱即用的基本页面设置集合;然而,页面模型是可扩展的。您将在第十章中学习如何扩展页面模型和添加额外的字段。
页面设置
页面设置菜单项提供与图 8-3 相同的设置。
模板
为页面选择一个模板。如果你遵循了第四章的说明,你应该有两个选择:页面和带侧边栏的博客页面。
高级设置
高级设置菜单允许您设置和修改许多高级页面设置(图 8-4 )。
- 覆盖 URL。用页面的自定义 URL 替换系统生成的 URL。
- 重定向。用于将旧页面重定向到新的 URL。也可用于重定向到外部 URL。
- 模板。与在页面设置中更改页面模板的效果相同。
- 身份证。这是一个超出本书范围的高级选项。它用于高级内部链接的模板标签中。
- 软根。在此页面创建软根。用于创建子菜单;当附加到菜单时,被检查为软根的页面将不显示任何祖先。下一章将详细介绍菜单。
- 附菜单。附加到此页面的自定义菜单。下一章将详细介绍菜单。
- 申请。向 Django 应用提供 apphook。你将在第十章中了解 apphooks。
- x 框架选项。设置页面是否可以嵌入到另一个页面中。用于防止您的网页在其他网站中被非法陷害。

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

图 8-5。
Page permissions
使用页面权限,您可以:
- 要求用户登录才能访问该页面。
- 隐藏菜单导航中的页面,只为特定用户显示菜单中的页面链接。
- 限制某些用户和组查看该页面。
- 添加或删除特定用户和组的页面编辑权限。
出版日期
发布日期菜单选项(图 8-6 )允许您设置页面发布的日期范围。可以为只在有限时间内显示的页面设置结束日期。

图 8-6。
Page publishing dates
在导航中隐藏
如果您不想在顶部菜单导航中显示页面,请选择此选项。
发布/取消发布页面
从出版物中发布或删除以前发布的页面。未发布的页面仅对编辑和管理员可见,并且不再出现在普通用户的导航菜单中。
删除页面
从 CMS 中删除页面。删除的页面可以在页面管理界面中恢复(请参阅本章后面的内容)。
另存为页面类型
页面类型是为特定类型的内容创建通用布局的非常有用的工具。例如,您可能有一个产品评论网站,其中每篇文章都有一张图片、一个摘要、详细信息,还可能有一个表格或选项卡来显示规格和建议。由于这种布局在您的网站上的所有产品评论中是通用的,但在一般的网站上不是通用的,所以您不希望修改网站模板。
将您的第一篇产品评论保存为页面类型可让您在所有产品评论中重复使用该格式。同样的原则也适用于您站点上任何想要复制格式或内容的内容。页面类型的另一个用途是在每篇文章的末尾有一个作者简介,在这里你不需要开发一个定制的插件。
请注意,当您第一次创建网站时,页面类型下拉列表是空的;没有默认的页面类型,您需要自己定义。
历史
django CMS 保留了对每个页面所做更改的详细历史记录。完整的页面历史可通过历史菜单访问(图 8-7 )。

图 8-7。
The History menu
History 菜单非常简单:有一个选项可以撤销当前的更改,也可以恢复到 live 版本,这将清除所有更改,恢复到当前发布的版本。
Caution
“恢复到实时”还会清除页面的所有已保存草稿。
查看历史将显示一个页面的完整历史(图 8-8 )。选择修订日期将为您提供恢复到所选修订的选项。

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

图 8-9b。
The toolbar buttons for an unpublished page

图 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 中包含了一个主页样本。请注意,您的页面不必看起来完全像这样;重要的是练习使用插件。

图 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 显示了这个页面可能的样子。

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

图 8-12。
A sample contact page
阶段 4:创建博客文章
使用部分或全部插件,创建另外两个名为“blogpost1”和“blogpost2”的页面然后选择页面➤隐藏在导航中,使这些页面不显示在顶部菜单中,并发布每个页面。我们将在下一章把这些页面链接到侧边菜单,稍后,一旦你学会了如何扩展页面模型,我们将创建一个名为“博客”的页面类别,以便在我们的侧边菜单和最新的文章页面上显示它们和任何后续的博客文章。
这就是目前的内容创作。接下来,我们将探讨如何管理 django CMS 网站。
django CMS 管理局
django CMS 管理界面通过根菜单(图 8-1 )选择 example.com➤管理进入。默认的管理仪表板如图 8-13 所示。根据您安装的第三方插件,您的管理仪表板可能会有所不同。

图 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 显示了在你完成之前的练习后,你的页面管理界面会是什么样子。如果您已经跳到前面,页面列表将是空白的。

图 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
| 工具 | 功能 | | --- | --- | |  | 根图标。如果页面是根页面,则显示。 | |  | 查看页面。选择以使此页面成为当前页面。 | |  | 已发布图标。如果页面已发布,则为绿色;如果页面有未发布的更改,则为蓝色;如果页面未发布,则为灰色。可以通过选择图标进行切换。 | |  | 在菜单图标中。已检查页面是否在顶部导航菜单中。通过选择图标可以直接切换该设置。 | |  | 编辑页面属性。编辑页面设置。您也可以按住 Shift 键选择以访问高级设置。请注意,您不能从管理员那里编辑页面内容或结构,只能编辑设置。 | |  | Copy page. When it is selected, the insert inside () 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 () to move the page to the desired position in the menu. | |  | 将子页面添加到当前页面。 | |  | Cut page. When it is selected, the insert inside () 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 () to move the page to the desired position in the menu, rather than cut and reinsert. | |  | 删除该页面。可以通过选择右上角的“恢复删除的页面”按钮来恢复。 | |  | Page information iconn Hover for basic page information. Example: |
用户管理
django CMS 用户管理如图 8-15 所示。可以从 django CMS ➤用户下的管理仪表板访问它,也可以通过工具栏 root(example.com)➤用户访问它。

图 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 ,您会看到左侧有一个权限列表,可以为每个对象选择权限。

图 8-16。
Setting user permissions
列表中有几十种权限;但是,它们都遵循相同的格式:<app> | <model> | <permission>,每个模型有三个权限,允许您分配添加、更改和/或删除权限。所有与 django CMS 核心相关的权限都列在 CMS 应用(cms| …)下,所有默认的插件应用权限都以djangocms_开头(例如,djangocms_column表示多列插件)。如果你遵循了书中的其他例子,你也会看到filer和easythumbnails插件的权限。
组
Django 组(图 8-17 )是一种创建类别的通用方法,可以将组权限应用于个人用户。分配给某个组的用户将继承分配给该组的所有权限。用户可以属于多个组。

图 8-17。
Django user groups
对于 CMS 来说,组提供了一个明显的优势,即能够定义一组权限(对于一个作者或一个编辑),然后可以应用到单个用户。在这个阶段,您可能很想这样做:创建作者和编辑组,并分别分配每个权限,但是 django CMS 附带了对 django 默认权限的扩展,使这变得容易多了。
django CMS 中的权限
django CMS 扩展了 django 的用户模型,并为在 django CMS 页面上设置权限提供了两个新模型:
- 用户组(第页)
- 用户(第页)
用户(页面)模型与 Django 模型几乎完全相同,所以我们在这里不再赘述,但是用户组(页面)模型(图 8-18 )增加了一些有用的功能,使得为常见的 CMS 任务设置权限变得非常简单。

图 8-18。
Adding a user group
例如,让我们创建一个名为 Editor 的新组。为新组添加以下权限:
- 页面权限:添加、更改和删除
- 用户和组权限:全部未选中
- 页面权限管理:全部未选中
这些权限反映了您对页面编辑器的期望:他们可以添加、更改和删除页面,但不能添加、更改或删除其他用户的权限。
如果您导航回管理仪表板并打开身份验证和授权➤组➤编辑器,您应该会看到类似图 8-19 的内容。

图 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导入了类Menu和NavigationNode,这意味着菜单将被附加到根菜单(主菜单)。 - 然后我们创建我们的
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 )。

图 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 所示。

图 9-2。
Custom menu attached to a page
虽然我们新的定制菜单令人印象深刻,但它并没有多大用处;菜单链接只是指向不存在的页面。如果链接指向我们的博客文章,它就会变得有用。我们这样做的方式非常简单;我们只需要用实际博客文章的标题和 URL 替换示例值title和url。
这很容易做到,但首先我们必须多理解 django CMS Page和Title模型。简而言之,django CMS 不会在一个模型中存储页面的所有信息;主要是它有一个Title模型,存储关于页面不同版本的信息(例如,语言版本、元数据和草稿版本)。Page模型存储与页面相关的信息,如发布日期、安全设置和页面模板。
Title和Page模型中的字段比我们在这里讨论的时间要多得多;我鼓励您浏览 django CMS 文档,以全面了解这些模型,因为它们是 django CMS 中更高级编程的核心。出于自定义菜单的目的,我们只对博客文章的标题及其 URL 感兴趣。容易吗?
不完全是。有几个需要注意的地方,理解发生了什么的最好方法是让我们稍微偏离一下主题,用 Python 交互式提示来探索一下Page和Title模型。打开一个命令窗口,确保您已经启动了虚拟环境。您的命令提示符应该如下所示:
(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不是识别博客文章的好方法,因为任何隐藏在主菜单中的页面都会出现在博客菜单中。因为我们要到下一章才会学习如何扩展Page和Title模型(添加一个类别字段),所以把这看作一个说明性的例子,而不是一个实用的例子!
让我们用交互式控制台对此进行测试:
>>> 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模型;由于page是Title模型的外键,我们可以从带点(.)运算符: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 并且
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 所示。

图 9-3。
Complete custom blog menu
正如我前面所说,这只是一个例子,说明在 django CMS 中构建自定义菜单是多么容易。我不建议将它作为显示博客文章的实用解决方案;对于初学者来说,一旦你有了更多的博客条目,这将创建一个笨拙的菜单。
在下一章中,一旦你学会了如何扩展Title和Page模型,你将能够构建更加实用的定制菜单。例如,一旦您为每个页面添加了一个类别字段,该菜单就可以链接到特定类别中的所有页面,并使用 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 }}"> 
{{ 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 所示。

图 9-4。
Our pages with the breadcrumb trail added
社交按钮
像脸书和推特这样的社交媒体网站非常受欢迎,可以分享各种内容,包括最喜欢的博客文章;如此受欢迎,以至于几乎所有受欢迎的博客网站上都有喜欢和分享社交媒体按钮。
django CMS 有几个第三方插件来实现与社交媒体平台的交互,包括喜欢和分享按钮;然而,在这一节,我将教你如何将简单的社交媒体功能直接嵌入到你的网站中。这是一项需要学习的有用技能,因为它可以应用于大量需要嵌入 HTML 片段和加载 JavaScript 库的应用、其他社交媒体网站和工具(如 Google Analytics)。
django CMS 让嵌入社交媒体功能变得非常简单;我们将使用一个静态占位符,一些来自脸书和 Twitter 的嵌入代码,以及一些 JavaScript 库的组合。一旦我们完成,你的博客文章底部会有分享按钮,如图 9-5 。

图 9-5。
Social media Share buttons added to blog pages
如果您还记得第五章中的,我们已经为blogpage.html添加了以下静态占位符:
{% static_placeholder "social" %}
从右侧导航菜单中选择一篇博客文章,并将其模板设置为带侧边栏的博客页面(带侧边栏的页面➤模板➤博客页面)。如果您切换到结构视图,您会注意到您已经切换到博客模板,该模板添加了社交按钮占位符(图 9-6 )。

图 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.html和blogpage.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 ',
{'sitemaps': {'cmspages': CMSSitemap}}),
)
. . .
如果你导航到 http://127.0.0.1:8000/en/sitemap.xml ,你应该会看到一个类似于图 9-7 的网站地图。

图 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 中的Page和Title模型。这个类别将在以后构建自定义菜单插件时使用。
然后,我们将探讨如何向您的网站添加任何类型的 Django 应用,无论是第三方应用还是您自己构建的应用。在这个练习中,我们将使用 Django 教程中的 Polls 应用,而不是从头开始构建自己的程序。然后,我将向您展示如何使用 django CMS apphook 将应用附加到您的网站上。
然后我们将看看 django CMS 的另一个可扩展部分——工具栏。我将向您介绍通过添加我们的投票应用来扩展工具栏,以便它可以从您的网站前端编辑。
最后,我将介绍自定义插件,并教你如何创建和实现你自己的自定义插件,用于你的应用,以及与其他 django CMS 用户共享。
扩展页面和标题模型
在前一章中,我使用了我们的博客页面来演示如何创建一个定制菜单,但是我注意到这不是一个健壮的例子,因为我们使用了in_navigation属性来标识博客文章。最好是一个类别属性,这样我们就可以通过类别来识别页面:一个页面类别用于网站上的静态页面,一个文章类别用于博客文章。
开箱即用,Title模型和Page模型都没有这样的属性。幸运的是,Page和Title模型都是可扩展的。扩展这些模型的能力是 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类中导入PageExtension和extension_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 )。

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

图 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'), 
url=url, disabled=not self.toolbar.edit_mode)
逐句通过代码,请注意以下事项:
- 我们用
toolbar_pool.register装饰器注册工具栏类。 - 我们让 django CMS 知道我们想要为工具栏项目使用
CategoryExtension模型。 - 为了将我们的模型添加到工具栏中,我们从
ExtensionToolbar中调用_setup_extension_toolbar()函数。这为我们的工具栏项目做了所有的初始化和设置。如果失败,它返回False,所以如果你的扩展模型有问题,这个函数会通过不加载你的类而优雅地失败。
输入代码后,保存cms_toolbar.py文件并重启服务器。如果您输入的一切都正确,现在您的页面菜单上会有一个新选项(图 10-3 )。

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

图 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 )。

图 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 )。

图 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)
逐句通过这段代码,请注意以下几点:
- 首先我们必须导入
CMSApp和ApphookPool类(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 )。

图 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'),
)
逐句通过这段代码,请注意以下几点:
- 首先我们必须导入
CMSToolbar和ToolbarPool类(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 (注意你必须在投票页面上才能看到)。

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

图 10-9。
Adding a new poll from the django CMS toolbar
另一方面,选择“投票列表”,将会展开侧边栏向您显示投票列表(图 10-10 )。

图 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中。

图 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()方法,将一个context和instance传递回你的模板。因为这是代码中最复杂的部分,所以接下来我会单独解释。
django CMS render()方法与 django 的render()方法基本相同,因为它返回用给定上下文呈现的给定模板的HTTPResponse对象。
在我们的插件中,模板是menu_plugin.html,我们将元组列表添加到上下文中(blogposts)。复杂性来自于我们需要访问本章开始时对Page模型的扩展的方式。
为了在我们的侧边菜单中创建锚文本和 URL,我们需要访问页面的标题和路径。如果你还记得第九章,title和path都是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的子类。因为CMSPluginBase是ModelAdmin的子类,CMS 插件开发者也可以使用几个重要的ModelAdmin选项。这些是最常用的:
excludefieldsfieldsetsformformfield_overridesinlinesradio_fieldsraw_id_fieldsreadonly_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 )。

图 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 )。

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

图 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 , 
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 
(page_id=post.extended_object_id).publisher_is_draft:
anchor = 
((Title.objects.get(page_id=post.extended_object_id).title),)
anchor += 
((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 )。

图 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 的一些更高级的特性。您学习了如何扩展Page和Title模型,以及如何向我们的项目添加 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 资源。以下是我写作时的一些佳作:
- Django 女孩教程(
http://tutorial.djangogirls.org/en/index.html) - 探戈与 Django(
http://www.tangowithdjango.com/book17/) - 掌握 Django(
www.masteringdjango.com)。声明:这是我的免费 Django 资源网站。 - 两勺 Django(
www.twoscoopspress.org
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。这个列表并不全面,但是考虑到开源环境不断变化的本质,它提供了一个起点,我希望这将是一个有价值的编程职业。
你现在已经到了这本书的结尾。我希望你像我喜欢写它一样喜欢学习这些材料,并祝你未来的编程之旅一切顺利!




浙公网安备 33010602011771号