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

Wagtail 2.0富文本内容添加Fragment ID链接的实现方案

Great question—Wagtail 2.0's default rich text editor doesn't have a built-in way to add explicit IDs to headings, or to link directly to those anchors from the editor's link tool. But there are three solid approaches to solve this, depending on whether you want user-defined IDs, auto-generated ones, or a quick manual workaround.


1. Build a Custom Rich Text Extension for User-Defined Heading IDs

This is the most flexible solution if you want content editors to set custom IDs for headings directly in the editor. You'll need to create a custom Draftail extension that adds heading options with ID support:

First, create a rich_text_extensions.py file in your Wagtail app:

from wagtail.core import hooks
from wagtail.admin.rich_text.converters.html_to_contentstate import BlockElementHandler
from wagtail.core.rich_text import RichTextExtension

class HeadingWithIdExtension(RichTextExtension):
    def construct_options(self, options):
        # Add our custom heading feature to the editor's feature list
        options['features'].append('heading-with-id')

    def register_features(self, features):
        # Register the editor plugin for H2 with ID support (repeat for H3/H4 as needed)
        features.register_editor_plugin(
            'draftail',
            'heading-with-id',
            {
                'type': 'heading-two',
                'label': 'H2 (with ID)',
                'description': 'Heading level 2 with custom anchor ID',
                'element': 'h2',
                'attributes': {'id': ''},  # Enable ID attribute editing
                'props': {'placeholder': 'Enter heading text...'},
            }
        )

        # Handle conversion between HTML and Draftail's content state
        features.register_converter_rule(
            'contentstate',
            'heading-with-id',
            {
                'from_database_format': {'h2[id]': BlockElementHandler('heading-two')},
                'to_database_format': {'block_map': {'heading-two': {'element': 'h2'}}},
            }
        )

@hooks.register('register_rich_text_extensions')
def register_heading_with_id_extension():
    return HeadingWithIdExtension()

Then, update your settings.py to ensure your app is in INSTALLED_APPS (so the hook loads), and add the new feature to your editor config:

WAGTAILADMIN_RICH_TEXT_EDITORS = {
    'default': {
        'WIDGET': 'wagtail.admin.rich_text.DraftailRichTextArea',
        'OPTIONS': {
            'features': [
                # Keep your existing features, plus the new one
                'bold', 'italic', 'link', 'heading-with-id'
            ]
        }
    },
}

Once set up, editors can select the "H2 (with ID)" option, and when editing the heading, they'll see a field to input the custom ID.


2. Auto-Generate Heading IDs (No Editor Input Required)

If you don't need custom IDs and just want automatic, slug-based anchors for headings, you can add a template filter to inject IDs when rendering the rich text:

Create a templatetags/custom_rich_text.py file:

from django import template
from bs4 import BeautifulSoup
from wagtail.core.rich_text import expand_db_html
from django.utils.text import slugify

register = template.Library()

@register.filter
def add_auto_heading_ids(value):
    # Expand Wagtail's stored rich text to full HTML
    html = expand_db_html(value)
    soup = BeautifulSoup(html, 'html.parser')

    # Add slugified IDs to all headings without existing IDs
    for heading in soup.find_all(['h1', 'h2', 'h3', 'h4', 'h5', 'h6']):
        if not heading.get('id'):
            heading_text = heading.get_text(strip=True)
            heading['id'] = slugify(heading_text)

    return str(soup)

Then use this filter in your template when rendering the rich text field:

{{ page.your_rich_text_field|add_auto_heading_ids|safe }}

This will automatically turn a heading like "Getting Started" into <h2 id="getting-started">Getting Started</h2>, which you can link to using #getting-started.


3. Manual HTML Editing (Quick Emergency Fix)

For one-off cases, you can enable HTML editing in the rich text editor and allow the id attribute for headings:

Update settings.py to whitelist the id attribute and enable source editing:

# Allow ID attribute for headings in rich text
from wagtail.core.whitelist import attribute_rule

WAGTAIL_CONTENT_WHITELIST = {
    'h1': attribute_rule({'id': True}),
    'h2': attribute_rule({'id': True}),
    'h3': attribute_rule({'id': True}),
    # Keep other default whitelisted tags here
}

# Enable source editing in Draftail
WAGTAILADMIN_RICH_TEXT_EDITORS = {
    'default': {
        'WIDGET': 'wagtail.admin.rich_text.DraftailRichTextArea',
        'OPTIONS': {
            'features': ['bold', 'italic', 'link', 'heading-1', 'heading-2', 'heading-3'],
            'show_expanded_formatting': True,  # Shows the "source" button
        }
    },
}

Editors can now click the "source" button in the editor, manually add id="your-anchor" to any heading, and save.


Final Notes

  • For linking to these anchors, you can use the editor's link tool and enter #your-heading-id as the URL.
  • The custom extension approach can be extended to add anchor selection directly in the link tool with extra frontend JavaScript, but the above gives you the core functionality.

内容的提问来源于stack exchange,提问作者Mike 'Pomax' Kamermans

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 11:50:31