> 文章列表 > wagtail 入门与使用 - 基于 Python Django 的内容管理系统 CMS

wagtail 入门与使用 - 基于 Python Django 的内容管理系统 CMS

wagtail 入门与使用 - 基于 Python Django 的内容管理系统 CMS

介绍与

wagtail 是一个内容管理系统,使用了 Django 作为底层的 MVC 服务框架,对于使用 Python 的小伙伴还是相当方便。wagtail 的功能包括:

  • 账号和角色管理,例如编辑、发布者等,拥有不同权限
  • 通过管理后台对内容、文档层级、附件、图片等进行管理
  • 支持游客浏览内容
  • 自定义知识库页面的内容板块
  • 可以集成评论等功能

wagtail 可以用来搭建自己的博客、文档知识库、新闻网站,甚至是论坛、电商平台。

基本概念

  • Django:一个 Python 的服务器框架,强烈建议希望使用 wagtail 的小伙伴先了解一下 Django 的一些基本概念和项目管理方式
  • CMS:内容管理系统,对内容的组织层级、发布流程等进行管理,同时协助进行内容分发
  • Page:wagtail 中比较重要的概念,内容的载体是 Page,可以针对不同类型的内容编写自己不同的 Page 类,例如新闻、目录、作家等

快速开始 - 新项目

如果你没用过接触过 Django,可以直接用 wagtail 提供的管理工具来做。

# 安装 wagtail
pip install wagtail # 要先安装 Python3,建议 3.8 及以上版本# 创建一个名为 mysite 的项目
wagtail start mysite# 安装必要包
cd mysite
pip install -r requirements.txt# 做数据库迁移,使用 Django 的 manage.py 工具来完成,默认使用 sqlite
python manage.py migrate# 创建超级账号,要输入账号名和两次密码
python manage.py createsuperuser# 测试
python manage.py runserver # 默认可以通过 http://localhost:8000 来访问

快速集成到现有的 Django 项目里

# 安装 wagtail
pip install wagtail

在 Django 项目的 settings.py 中增加配置

INSTALLED_APPS = [...'wagtail.contrib.forms','wagtail.contrib.redirects','wagtail.embeds','wagtail.sites','wagtail.users','wagtail.snippets','wagtail.documents','wagtail.images','wagtail.search','wagtail.admin','wagtail','modelcluster','taggit',...
]MIDDLEWARE = [...'wagtail.contrib.redirects.middleware.RedirectMiddleware',...
]# 配置 STATIC_ROOT,用于放置 static 文件
STATIC_ROOT = os.path.join(BASE_DIR, 'static')# 配置 media 相关配置,根据项目需要设置
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = '/media/'

在 urls.py 中对路由进行配置

from django.urls import path, includefrom wagtail.admin import urls as wagtailadmin_urls
from wagtail import urls as wagtail_urls
from wagtail.documents import urls as wagtaildocs_urlsurlpatterns = [...path('cms/', include(wagtailadmin_urls)), # 管理中心path('documents/', include(wagtaildocs_urls)), # 文件path('pages/', include(wagtail_urls)), # 知识页面...
]## 可能要设置 media_root
from django.conf import settings
from django.conf.urls.static import staticurlpatterns = [# ... the rest of your URLconf goes here ...
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

添加页面类型

当完成部署之后,你会发现无法添加子页面,或者页面只有标题,没有内容,这是正常的。
因为 wagtail 没有自带一些标准页面(Page),例如新闻、推文……需要我们根据自己的需求来写页面。具体的步骤是这样的:

# 在 Django 项目里新建一个新应用,这里以 blog 为名称进行举例
python manage.py startapp blog
# blog 也会被放置到 Django 的 Settings.py 中的 INSTALLED_APP 里

在 blog 文件夹的 models.py 中写自己的新页面,举个例子

from django.db import modelsfrom modelcluster.fields import ParentalKeyfrom wagtail.models import Page, Orderable
from wagtail.fields import RichTextField
from wagtail.admin.panels import FieldPanel, MultiFieldPanel, InlinePanel
from wagtail.search import indexclass BlogPage(Page):# 页面有 title(标题,Page 类自带)、body(内容)、date(日期)、feed_image(头图)三个# feed_image 是外部键,是 wagtailimages.Image 类body = RichTextField()date = models.DateField("Post date")feed_image = models.ForeignKey('wagtailimages.Image',null=True,blank=True,on_delete=models.SET_NULL,related_name='+')# 可以通过 body 搜索,通过 date 筛选search_fields = Page.search_fields + [index.SearchField('body'),index.FilterField('date'),]# 在 cms 管理后台中,当新建 1 个 BlogPage 时,会出现 date、body、related_links(相关链接) 字段# 其中 related_links 是 wagtail 中实现 many-to-many 关系的方式,下边会提到content_panels = Page.content_panels + [FieldPanel('date'),FieldPanel('body'),InlinePanel('related_links', heading="Related links", label="Related link"),]# 在 cms 管理后台中,当新建 1 个 BlogPage 时,高级选项里会出现常见 common page configuration、feed_image 选项promote_panels = [MultiFieldPanel(Page.promote_panels, "Common page configuration"),FieldPanel('feed_image'),]# 在哪些类型的页面下可以创建 BlogPage 作为子页面、BlogPage 下可以创建哪些子页面,空就是无限制parent_page_types = []subpage_types = []# 定义了 related_link(相关链接)的类
class BlogPageRelatedLink(Orderable):# 和 BlogPage 相关联的字段page = ParentalKey(BlogPage, on_delete=models.CASCADE, related_name='related_links')# 链接名称和 urlname = models.CharField(max_length=255)url = models.URLField()# 当在 cms admin 里添加相关链接时,有哪些字段panels = [FieldPanel('name'),FieldPanel('url'),]

当这个页面写完后

python manage.py makemigrations
python manage.py migrate
python manage.py runserver

从浏览器进入管理后台,在上面的例子里就是 http://localhost:8000/cms/ 这个地址,此时再尝试添加页面的时候,就会出现 Blog Page 这个类型。

这里再说明一下背后机制,方便大家理解:

  1. Page 是 wagtail 提供的核心类,是 Django 的一个 Model,在数据库中会有对应的表
  2. 当写了一个 BlogPage 继承了 Page 后,也会在数据库中建立 1 个表
  3. 当创建了 1 个页面时,会在 Page 的表中新增 1 个记录,在 BlogPage 表中新增 1 个记录,其中 Page 记录中的 specific 字段,将指向 BlogPage 表中的记录

进行页面渲染

页面渲染也是使用 Django 的 templates 机制实现的。

首先刚刚创建的应用名称为 blog,那么需要在 blog 文件夹下创建 templates 文件夹,其下创建 blog 文件夹(和应用同名),刚刚距离的页面名称为 BlogPage,所以在这个文件夹下,创建 blog_page.html 文件,这样 wagtail 就能找到这个模板了,此时打开相关页面就会通过这个模板进行渲染,下面举个例子

<!--打开 blog_page.html --><!--加载 wagtail 能力 -->
{% load wagtailcore_tags %}
{% load wagtailimages_tags %}<html><head><!--page 是传进来的参数,通过 get_site 获取站点信息,site_name 是站点名称--><title>{{ page.get_site.site_name }}</title><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><!--引入了 bootstrap--><link rel="stylesheet" href="http://cdn.bootcss.com/bootstrap/5.2.0/css/bootstrap.min.css"></head><body><!--这里是面包屑--><nav aria-label="breadcrumb"><ol class="breadcrumb" style="flex-wrap: nowrap; overflow: auto;white-space: nowrap;"><!--self.get_ancestors 获取父页面,.specific 获取具体的记录-->{% for p in self.get_ancestors.specific %}{% if p.title != 'Root' %}<!--每条记录获取 url(.get_url),名称(.title) --><li class="breadcrumb-item"><a href="{{ p.get_url }}">{{ p.title }}</a></li>{% endif %}{% endfor %}<li class="breadcrumb-item active" aria-current="page">{{ page.title }}</li></ol></nav><div style="margin: 12px;"><!--页面标题--><h1>{{ page.title }} </h1><!--头图,使用 image 标签,设置宽度 400-->{% image page.feed_image width-400 %}<!--内容-->{{ page.body }}<!--相关链接--><ul class="list-group">{% for l in page.related_links %}<a href="{{ l.get_url }}" class="list-group-item list-group-item-action">{{ l.name }}</a>{% endfor %}</ul></div></body>
</html>

此时就可以在 cms admin 里正常预览页面了,点击打开页面也可以正常浏览了

结语

以上,初步演示了 wagtail 的使用流程,诸如插件推荐、Django 项目的部署等问题,此处都没有涉及。欢迎交流。