wagtail 是一个内容管理系统,使用了 Django 作为底层的 MVC 服务框架,对于使用 Python 的小伙伴还是相当方便。wagtail 的功能包括:
wagtail 可以用来搭建自己的博客、文档知识库、新闻网站,甚至是论坛、电商平台。
如果你没用过接触过 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 来访问
# 安装 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, include
from wagtail.admin import urls as wagtailadmin_urls
from wagtail import urls as wagtail_urls
from wagtail.documents import urls as wagtaildocs_urls
urlpatterns = [
...
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 static
urlpatterns = [
# ... 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 models
from modelcluster.fields import ParentalKey
from wagtail.models import Page, Orderable
from wagtail.fields import RichTextField
from wagtail.admin.panels import FieldPanel, MultiFieldPanel, InlinePanel
from wagtail.search import index
class 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')
# 链接名称和 url
name = 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
这个类型。
这里再说明一下背后机制,方便大家理解:
页面渲染也是使用 Django 的 templates 机制实现的。
首先刚刚创建的应用名称为 blog
,那么需要在 blog
文件夹下创建 templates
文件夹,其下创建 blog
文件夹(和应用同名),刚刚距离的页面名称为 BlogPage
,所以在这个文件夹下,创建 blog_page.html
文件,这样 wagtail 就能找到这个模板了,此时打开相关页面就会通过这个模板进行渲染,下面举个例子
{% load wagtailcore_tags %}
{% load wagtailimages_tags %}
<html>
<head>
<title>{{ page.get_site.site_name }}title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<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;">
{% for p in self.get_ancestors.specific %}
{% if p.title != 'Root' %}
<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 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 项目的部署等问题,此处都没有涉及。欢迎交流。