You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何从Wagtail StreamField提取纯文本并去格式?含额外疑问

问题解答

一、提取纯文本的两种实现方式

你可以选择在Wagtail模型层处理,也可以在模板层用自定义过滤器实现,两种方式都能得到不带格式的纯文本:

1. 模型层处理(推荐)

在你的PostPage模型中添加一个方法,专门提取正文里的纯文本摘要,逻辑是遍历StreamField的所有块,只处理paragraph类型的内容,剥离HTML标签后截断到指定字数:

from django.utils.html import strip_tags
from django.utils.text import truncate_words
from wagtail.models import Page

class PostPage(Page):
    body = StreamField([
        ('heading', blocks.CharBlock()),
        ('paragraph', blocks.RichTextBlock()),
        ('image', ImageChooserBlock()),
    ], blank=True)

    # 新增方法:获取纯文本摘要
    def get_plain_text_summary(self, word_count=10):
        plain_text_content = ""
        # 遍历StreamField的每个块
        for block in self.body:
            # 只处理段落块
            if block.block_type == 'paragraph':
                # 提取RichText的原始HTML,剥离标签得到纯文本
                html_content = block.value.source
                plain_text = strip_tags(html_content)
                plain_text_content += plain_text + " "
        # 截断到指定字数
        return truncate_words(plain_text_content, word_count)

之后在模板里直接调用这个方法即可:

{% for blog in blogs %}
    <a class="blog-post-link" href="{% pageurl blog %}">{{ blog.title}}</a>
    {{ blog.get_plain_text_summary }}
    <a href="{% pageurl blog %}">Read More</a>
{% endfor %}

2. 模板层自定义过滤器

如果不想修改模型,可以创建一个自定义模板过滤器,实现同样的逻辑:

  1. 在你的Django应用下创建templatetags/wagtail_stream_utils.py文件,内容如下:
from django import template
from django.utils.html import strip_tags
from django.utils.text import truncate_words

register = template.Library()

@register.filter
def streamfield_plain_text(streamfield, word_count=10):
    plain_text = ""
    for block in streamfield:
        if block.block_type == 'paragraph':
            html_content = block.value.source
            text = strip_tags(html_content)
            plain_text += text + " "
    return truncate_words(plain_text, word_count)
  1. 在模板中加载过滤器并使用:
{% load wagtail_stream_utils %}

{% for blog in blogs %}
    <a class="blog-post-link" href="{% pageurl blog %}">{{ blog.title}}</a>
    {{ blog.body|streamfield_plain_text:10 }}
    <a href="{% pageurl blog %}">Read More</a>
{% endfor %}

二、关于StreamField展示行为的稳定性

你当前看到的“直接跳转到第一个段落”的行为不稳定,因为默认情况下blog.body会渲染所有块的HTML(包括heading的标题、image的图片标签),truncatewords_html只是对渲染后的整体HTML进行截断。如果你的StreamField第一个块是heading,截断结果会包含标题文本;如果是image,可能会保留图片的alt文本(如果设置了的话)。

要保证行为稳定,必须显式指定只提取paragraph块的内容——也就是上面两种方法里的逻辑:遍历StreamField时只处理block_type == 'paragraph'的块,完全忽略heading和image。这样不管你后续调整StreamField的块顺序,摘要都会只从段落内容中提取,行为完全可控。

内容的提问来源于stack exchange,提问作者Jake Rankin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 23:10:56