我正在尝试在 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.search
。 re.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/