Python技术迷

wagtail,一个强大的 Python 库!

后台一旦开始长成“很多表单 + 一堆富文本 + 几种页面模板 + 运营老改内容”,纯 Django 很快就写得别别扭扭。模型能写,后台也能凑,真到线上用起来,编辑一顿点,开发一顿补。 这种活,我一般不太愿意从零搓 CMS,八成越写越像半成品。 这时候 Wagtail 就很顺手了。它不是那种只会发文章的博客壳子,而是把“内容模型、页面树、编辑后台、发布流程”这几件事直接给你接住了。

Wagtail 最值钱的地方,不是“基于 Django”,这个很多人都知道。真正好用的是它把内容管理这件事做得比较像样:页面本身就是模型,后台编辑器不是摆设,内容结构也不是一坨 HTML 塞数据库里,后面想扩字段、做列表、挂推荐位,都还接得住。

我第一次用它,不是拿来做新闻站,而是做一个产品内容站:有首页、专题页、文档页、案例页,每种页面长得都不一样。要是直接上 Django Admin,运营同学基本用不动;要是自己写后台,时间又不值钱。Wagtail 这种场景就挺合适。

先看个最常见的页面模型,别上来整太全,关键几行够了:

from django.db import models
from wagtail.models import Page
from wagtail.fields import RichTextField
from wagtail.admin.panels import FieldPanel

classArticlePage(Page):
    summary = models.CharField(max_length=160, blank=True)
    body = RichTextField(blank=True)
    author = models.CharField(max_length=32, default="")

    content_panels = Page.content_panels + [
        FieldPanel("summary"),
        FieldPanel("body"),
        FieldPanel("author"),
    ]

这段代码看着很普通,但味道已经不一样了。ArticlePage 不是一张孤零零的表,它天然就是页面;加到 Wagtail 里之后,路由、后台录入、预览、发布流程就都能跟上。这个比“我先建个 article 表,再单独写后台,再单独配前台 URL”省事得多。

再往前走一步,Wagtail 很适合做“内容块拼装”。很多站点最烦的不是文章,而是首页:上面一块 Banner,中间三列卡片,下面一个 FAQ,再插一段活动区。你要是还拿一整段富文本硬塞,后面肯定难维护。

这类页面我一般直接上 StreamField,让内容按块组装:

from wagtail.fields import StreamField
from wagtail import blocks

classHomePage(Page):
    body = StreamField([
        ("hero", blocks.StructBlock([
            ("title", blocks.CharBlock()),
            ("subtitle", blocks.TextBlock(required=False)),
        ])),
        ("notice", blocks.RichTextBlock()),
        ("cta", blocks.StructBlock([
            ("text", blocks.CharBlock()),
            ("link", blocks.URLBlock()),
        ])),
    ], use_json_field=True, blank=True)

这个设计有个很现实的好处:运营想改首页,不用找你发版。 想加一块说明,就在后台插;想把 CTA 往上拖,也不用改模板逻辑。很多团队嘴上说“低代码”,其实最后还是开发改。Wagtail 在内容层面,是真的能把一部分活放出去。

当然,它也不是没门槛。 Wagtail 用得舒服的前提,是你一开始就把“页面类型”和“内容结构”想清楚。这个地方我通常会先画棵树:首页下面能挂什么,专题页下面能不能再挂详情页,列表页到底是不是 Page,还是普通 Django view。这个顺序别反,不然后面越补越乱。

比如限制某个页面下面只能创建指定子页面,直接在模型里卡住:

classDocIndexPage(Page):
    subpage_types = ["DocPage"]

classDocPage(Page):
    parent_page_types = ["DocIndexPage"]

这几行很小,线上价值不小。 因为很多 CMS 到后面不是技术问题,是内容结构被人点坏了。运营能新建任何页面,看着自由,实际是灾难。Wagtail 至少给了你比较自然的约束手段。

还有一个我比较喜欢的点,是它和 Django 没割裂。 你原来的用户体系、权限、中间件、ORM 查询、接口逻辑,基本都能照着接。不是那种换个 CMS 就像换了半个技术栈。你甚至可以一边用 Wagtail 管页面,一边正常写 Django API。

比如页面里取在线文章列表,还是老老实实 ORM:

defget_context(self, request):
    context = super().get_context(request)
    context["latest_articles"] = ArticlePage.objects.live().public().order_by("-first_published_at")[:5]
return context

这种感觉就比较踏实。不是黑盒,不会让你一碰业务逻辑就出戏。

那 Wagtail 适合谁? 要我说,特别适合这几类项目:公司官网、内容站、品牌站、文档站、活动专题、轻量会员内容平台。页面多,模板多,编辑频繁,但又没复杂到要前后端都拆得很狠。 要是你只是做个纯接口服务,或者后台数据录入非常规整,Wagtail 就不一定是最优解。别看见 CMS 就往上套。

最后提一句,很多人第一次上 Wagtail,容易把它当“漂亮点的 Django Admin”。这看法偏了。 它本质上是个内容建模框架,顺手附带了一个能用的后台。用得好,重点不是页面多炫,而是内容结构没烂,后台真有人肯用,后面加字段、改模板、扩页面类型时,不至于一改就牵一片。 这种库,平时不显山露水,真到项目开始长肉的时候,你会觉得它省掉的不是几百行代码,是后面那一串返工。