让外部链接在一个令人讨厌的新窗口中打开

Chr*_*rry 6 html python django hook wagtail

我最近实现了添加target="_blank"到这样的外部链接:

@hooks.register('after_edit_page')
def do_after_page_edit(request, page):
    if hasattr(page, "body"):
        soup = BeautifulSoup(page.body)
        for a in soup.findAll('a'):
            if hasattr(a, "href"):
            a["target"] = "_blank"
        page.body = str(soup)
        page.body = page.body.replace("<html><head></head><body>", "")
        page.body = page.body.replace("</body></html>", "")
        page.body = page.body.replace("></embed>", "/>")
        page.save()

@hooks.register('construct_whitelister_element_rules')
def whitelister_element_rules():
    return {
        'a': attribute_rule({'href': check_url, 'target': True}),
    }
Run Code Online (Sandbox Code Playgroud)

问题:

  1. 美丽的汤混淆输出,添加html, head & body标签 - 不要自动放置html,头部和身体标签,beautifulsoup

  2. 它也与嵌入标签混淆 - 如何让BeautifulSoup 4尊重自动关闭标签?

  3. 因此我蹩脚的" fix"用空字符串手动替换部分输出.

题:

这样做的正确和最佳方法是什么?

小智 7

一直在努力解决同样的问题,并且无法使用wagtailhooks实现它.我最初的解决方案是使用过滤器操纵base.html中的内容.当放置在内容块中时,用于剪切代码片段的过滤器非常有效,例如:

{{ self.body|cut: ‘ href="http:’}}
Run Code Online (Sandbox Code Playgroud)

上面的过滤器会删除部分内容,但遗憾的是"替换"不能用作过滤器(我使用的是Python 3.x).因此,我的下一个方法是构建一个custom_filter来创建'replace'作为过滤选项.长话短说:它部分有效,但前提是内容从原始的'StreamValue'数据类型转换为'string'.此转换导致显示所有html标记的内容,因此替换不会导致工作html.我无法再将内容恢复到StreamValue,没有其他Python数据类型可以解决问题.最终JQuery为我完成了工作:

$(document).ready(function(){
$('a[href^="http://"]').attr('target', '_blank');
});        
Run Code Online (Sandbox Code Playgroud)

此代码将"target ="_ blank"'添加到包含"http://"的每个链接,因此所有内部链接都保留在现有选项卡中.它需要放在base.html(或类似的)的末尾,当然你需要在运行它之前加载它.从这里得到了答案.不知道JQuery是否是正确的,最好的方法,但它对我来说就像一个最小编码的魅力.

  • 你还应该添加`$('a [href ^ ="https://"]').attr('target','_ blank');`来覆盖https网址. (3认同)

Thi*_*las 5

从Wagtail v2.5开始,作为Wagtail的RTF处理的一部分,有一个API可以Rewrite handlers通过register_rich_text_features钩子进行自定义。

这是使用此新API进行重写处理程序的示例,该处理程序将target="_blank"属性设置为所有外部链接:

from django.utils.html import escape
from wagtail.core import hooks
from wagtail.core.rich_text import LinkHandler


class NewWindowExternalLinkHandler(LinkHandler):
    # This specifies to do this override for external links only.
    # Other identifiers are available for other types of links.
    identifier = 'external'

    @classmethod
    def expand_db_attributes(cls, attrs):
        href = attrs["href"]
        # Let's add the target attr, and also rel="noopener" + noreferrer fallback.
        # See https://github.com/whatwg/html/issues/4078.
        return '<a href="%s" target="_blank" rel="noopener noreferrer">' % escape(href)


@hooks.register('register_rich_text_features')
def register_external_link(features):
    features.register_link_type(NewWindowExternalLinkHandler)
Run Code Online (Sandbox Code Playgroud)

在这个例子中,我也加入rel="noopener"到解决一个已知的安全问题target="_blank"


与以前解决此问题的方法相比,此新方法最可靠:它完全在服务器端,并且仅覆盖如何在站点的前端呈现链接而不是如何存储链接,并且仅依靠文档化的API,而不是内部的API。 /实施细节。

  • 鉴于此解决方案适用于新版本的 wagtail,无需使用 JS/JQuery 进行黑客攻击,我请求 @Chris Berry 将其标记为已接受的答案。 (3认同)