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, 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 这个类型。

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

  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 就能找到这个模板了,此时打开相关页面就会通过这个模板进行渲染,下面举个例子




{% 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 项目的部署等问题,此处都没有涉及。欢迎交流。

你可能感兴趣的:(django,python)