如何从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. 模板层自定义过滤器
如果不想修改模型,可以创建一个自定义模板过滤器,实现同样的逻辑:
- 在你的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)
- 在模板中加载过滤器并使用:
{% 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
相关产品推荐
相关产品推荐

