在自定义Python Markdown扩展中禁用HTML编码

5 投票
2 回答
1256 浏览
提问于 2025-04-17 10:32

我一直在开发一个Python的Markdown扩展,目的是在我的Django项目中使用自定义标签插入一个图片画廊。这个扩展目前是可以工作的,但它返回的HTML内容都是经过编码的。以下是我使用的扩展:

#!/usr/bin/env python
from django.template.loader import render_to_string
from main.models import *

import markdown

version = "0.1.0"

class GalleriaExtension(markdown.Extension):
    def __init__(self, configs):
        self.config = {
        }

        # Override defaults with user settings
        for key, value in configs:
            self.setConfig(key, value)

    def add_inline(self, md, name, klass, re):
        pattern = klass(re)
        pattern.md = md
        pattern.ext = self
        md.inlinePatterns.add(name, pattern, "<reference")

    def extendMarkdown(self, md, md_globals):
        self.add_inline(md, 'galleria', Galleria,
            r'\[\[(G|g)allery (?P<superpage_id>\w+)\]\]')

class Galleria(markdown.inlinepatterns.Pattern):
    def handleMatch(self, m):
        try:
            images = SuperPage.objects.get(id=m.group('superpage_id')).superpageimage_set.all()
        except:
            images = None
        if images:
            rendered = render_to_string('galleria.html', { 'images': images })
        else:
            rendered = '<b>There are no images for the given ID</b>'
        return rendered 

def makeExtension(configs=None) :
    return GalleriaExtension(configs=configs)

我确保了render_to_string确实返回的是没有编码的HTML。下面是我在命令行中得到的输出示例:

来自render_to_string的输出:

>>> from django.template.loader import render_to_string
>>> images = SuperPage.objects.get(id=8).superpageimage_set.all()
>>> render_to_string('galleria.html', { 'images': images })
u'<div class=\'galleria_std\'>\n    <div class=\'gallery\' >\n      <div id=\'stage_gallery\' >\n'

这是来自Markdown扩展的编码输出:

>>>markdown.markdown('test [[gallery 8]] test', ['galleria'])
u'<p>test &lt;div class=\'galleria_std\'&gt;\n    &lt;div class=\'gallery\' &gt;\n'

我该如何让rendered在使用Markdown扩展时返回HTML标记,而不是编码后的标记呢?另外,如果有关于如何以不同方式编写代码的建议(语法、布局等),我也非常感激。

2 个回答

1

我这样解决了这个问题:

import markdown
from markdown import Extension
from markdown.inlinepatterns import Pattern
from django.template.loader import render_to_string
from gallery.models import Gallery

class InlineGalleryExtension(Extension):
    def extendMarkdown(self, markdownInstance, md_globals):
        GALLERY_RE = r'\[\[gallery (?P<id>[0-9]+)\]\]'
        inlineGalleryPattern = InlineGallery(GALLERY_RE, markdownInstance)

        markdownInstance.inlinePatterns.add('gallery', inlineGalleryPattern, "<not_strong")

class InlineGallery(Pattern):
    def handleMatch(self, m):
        try:
            gallery = Gallery.objects.get(id=m.group('id').strip())
        except Gallery.DoesNotExist:
            gallery = None

        if gallery:
            element = render_to_string('gallery/inline_gallery.html', {
                'gallery': gallery
            })
        else:
            element = ''

        return self.markdown.htmlStash.store(self.unescape(element))

关键的解决方法在最后一行。

3

如果你想要避免自定义标签渲染的内容被自动转义,那么你可以使用 django.utils.safestring.mark_safe 来标记这个字符串为安全的。

你可以在 Django 的代码中看到一些例子,比如在 defaulttags.py 文件里。

撰写回答