python - Django,自定义模板过滤器 - 正则表达式问题

标签 python regex django django-templates

我正在尝试在 Django 中实现一个 WikiLink 模板过滤器,它查询数据库模型以根据页面的存在给出不同的响应,与维基百科的红色链接相同。过滤器不会引发错误,而是不会对输入执行任何操作。

WikiLink 定义为:[[ThisIsAWikiLink | This is the alt text]]

这是一个不查询数据库的工作示例:

from django import template
from django.template.defaultfilters import stringfilter
from sites.wiki.models import Page
import re

register = template.Library()

@register.filter
@stringfilter
def wikilink(value):
    return re.sub(r'\[\[ ?(.*?) ?\| ?(.*?) ?\]\]', r'<a href="/Sites/wiki/\1">\2</a>', value)
wikilink.is_safe = True

输入 ( value ) 是一个多行字符串,包含 HTML 和许多维基链接。

预期的输出替换为[[ThisIsAWikiLink | This is the alt text]]

  • <a href="/Sites/wiki/ThisIsAWikiLink">This is the alt text</a>

    如果数据库中不存在“ThisIsAWikiLink”:

  • <a href="/Sites/wiki/ThisIsAWikiLink/edit" class="redlink">This is the alt text</a>

和返回值。

这是非工作代码(根据评论/答案编辑):

from django import template
from django.template.defaultfilters import stringfilter
from sites.wiki.models import Page
import re

register = template.Library()

@register.filter
@stringfilter
def wikilink(value):
    m = re.match(r'\[\[ ?(.*?) ?\| ?(.*?) ?\]\]', value)

    if(m):
        page_alias = m.group(2)
        page_title = m.group(3)
        try:
            page = Page.objects.get(alias=page_alias)
            return re.sub(r'(\[\[)(.*)\|(.*)(\]\])', r'<a href="Sites\/wiki\/\2">\3</a>', value)
        except Page.DoesNotExist:
             return re.sub(r'(\[\[)(.*)\|(.*)(\]\])', r'<a href="Sites\/wiki\/\2\/edit" class="redlink">\3</a>', value)
    else:
        return value
wikilink.is_safe = True

代码需要做的是:

  • 提取中的所有维基链接
  • 查询Page模型以查看页面是否存在
  • 将所有 WikiLink 替换为普通链接,样式取决于每个维基页面的存在。
  • 返回修改后的

更新后的问题是: 什么正则表达式(方法)可以返回一个python 维基链接列表,可以更改并用于替换原始匹配(更改后)。

编辑:

我想做这样的事情:

def wikilink(value):
    regex = re.magic_method(r'\[\[ ?(.*?) ?\| ?(.*?) ?\]\]', value)

    foreach wikilink in regex:
         alias = wikilink.group(0)
         text = wikilink.group(1)

         if(alias exists in Page):
              regex.sub("<a href="+alias+">"+ text +"</a>")
         else:
              regex.sub("<a href="+alias+" class='redlink'>"+ text +"</a>")

    return value

最佳答案

如果您的字符串除了 wiki 链接之外还包含其他文本,您的过滤器将不起作用,因为您使用的是 re.match 而不是 re.searchre.match 匹配字符串的开头。 re.search 匹配字符串中的任何位置。参见 matching vs. searching .

此外,您的正则表达式使用了贪婪的 *,因此如果一行包含多个 wiki 链接,它将不起作用。使用 *? 使其成为非贪婪的:

re.search(r'\[\[(.*?)\|(.*?)\]\]', value)

编辑:

关于如何修复代码的提示,我建议您使用 re.sub with a callback .优点是:

  • 如果您在同一行中有多个 wiki 链接,它会正常工作。
  • 遍历字符串就足够了。您不需要通行证来查找 wiki 链接,也不需要另一个通行证来进行替换。

下面是实现的草图:

import re

WIKILINK_RE = re.compile(r'\[\[(.*?)\|(.*?)\]\]')

def wikilink(value):
  def wikilink_sub_callback(match_obj):
    alias = match_obj.group(1).strip()
    text = match_obj.group(2).strip()
    if(alias exists in Page):
      class_attr = ''
    else:
      class_attr = ' class="redlink"'
    return '<a href="%s"%s>%s</a>' % (alias, class_attr, text)

  return WIKILINK_RE.sub(wikilink_sub_callback, value)

关于python - Django,自定义模板过滤器 - 正则表达式问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/902184/

相关文章:

python - PyQt5 QTableWidget : select column with right click, 并在上下文菜单中显示删除条目

javascript - 时区和 DateTimeField - Django

python - Scrapy 和 Django 导入报错

python - 迭代 Flask 中提交的表单字段?

Python 等同于 C 编程技术(while 循环)

python - 一种在 Python 中按欧氏距离对复数进行排序的有效方法

javascript - 找到所有链接并用它们的 href 值替换它们

javascript - RegExp 用于匹配字符串开头的协议(protocol)相对 URL

regex - 使用 PostgreSQL regexp_replace 函数删除连续的重复字符

Django Rest Framework - @detail_route 的详细信息页面