Django:错误的组名
我遇到了一个“坏的组名”的错误。
这是我的代码:
for qitem in q['display']:
if qitem['type'] == 1:
for keyword in keywordTags.split('|'):
p = re.compile('^' + keyword + '$')
newstring=''
for word in qitem['value'].split():
if word[-1:] == ',':
word = word[0:len(word)-1]
newstring += (p.sub('<b>'+word+'</b>', word) + ', ')
else:
newstring += (p.sub('<b>'+word+'</b>', word) + ' ')
qitem['value']=newstring
然后这是错误信息:
错误发生在 /result/1/ 坏的组名 请求方式: GET Django 版本: 1.4.1 异常类型: 错误 异常信息: 坏的组名 异常位置: C:\Python27\lib\re.py 的 _compile_repl, 第257行 Python 可执行文件: C:\Python27\python.exe Python 版本: 2.7.3 路径: ['D:\ExamPapers', 'C:\Windows\SYSTEM32\python27.zip', 'C:\Python27\DLLs', 'C:\Python27\lib', 'C:\Python27\lib\plat-win', 'C:\Python27\lib\lib-tk', 'C:\Python27', 'C:\Python27\lib\site-packages'] 服务器时间: 2013年3月3日 星期日 15:31:05 +0800
错误追踪信息 切换到复制粘贴视图
C:\Python27\lib\site-packages\django\core\handlers\base.py 中的 get_response response = callback(request, *callback_args, **callback_kwargs) ... ▶ 本地变量 ? D:\ExamPapers\views.py 中的 result newstring += (p.sub(''+word+'', word) + ' ') ... ▶ 本地变量
总之,错误出现在:
newstring += (p.sub('<b>'+word+'</b>', word) + ' ')
1 个回答
你想要把一组关键词加粗显示,但现在这段代码有很多问题。你正在使用 re
模块来匹配关键词,但同时又把关键词和字符串拆分成了单个单词,其实你不需要这样做。这两种解决问题的方法相互影响,导致了你的问题。
你可以使用正则表达式一次匹配多个可能的字符串,这正是它们的强项!所以,不要只用 "^keyword$"
来匹配“keyword”,你可以用 "^keyword|hello$"
来匹配 任意 一个“keyword”或“hello”。你还使用了 ^
和 $
这两个字符,它们只匹配整个字符串的开头或结尾,但你可能想要的是匹配单词的开头或结尾。为此,你可以使用 \b
,像这样 r"\b(keyword|hello)\b"
。注意在最后一个例子中,我在字符串前加了一个 r
字符,这表示“原始字符串”,可以关闭 Python 对反斜杠字符的常规处理,这样就不会和正则表达式冲突。通常在包含正则表达式的字符串前加 r
是个好习惯。我还用括号把单词分组。
正则表达式的 sub
方法可以用来把匹配到的内容替换成另一个字符串。它还允许你在替换的字符串中使用“反向引用”,也就是包含原始字符串中匹配的部分。这些部分叫做“组”,在原始正则表达式中用括号表示。在上面的例子中,只有一组括号,所以用反向引用 \1
来表示。你提到的错误信息的原因是你的替换字符串中包含了看起来像反向引用的内容,但你的正则表达式中没有组。
使用这个,你可以这样做:
keywordMatcher = re.compile(r"\b(keyword|hello)\b")
value = keywordMatcher.sub(r"<b>\1</b>", value)
还有一件事虽然和你问的问题不直接相关,但非常重要,那就是你正在把源文本字符串(我假设是这样)转换成 HTML,这样做会有很多脚本注入的漏洞。如果你不花时间去理解和避免这些漏洞,坏人就能轻易地攻击你构建的应用程序(他们可以自动化操作,所以即使你觉得你的应用太小,不会被人注意,仍然可能被攻击并用于各种坏事,千万不要让这种事情发生!)。基本规则是,转换文本为 HTML 是可以的,但你需要先“转义”它,这个过程非常简单:
from django.utils import html
html_safe = html.escape(my_text)
这只是把像 <
这样的字符转换成 <
,浏览器会显示为 <
,但不会把它当作标签的开始。所以如果坏人在你的表单中输入 <script>
,经过你的代码处理后,它会显示为 <script>
,而不会执行这个脚本。
同样,如果你在正则表达式中使用了不想作为特殊字符的文本,你也必须对它进行转义!你可以使用 re.escape
来做到这一点:
import re
my_regexp = re.compile(r"\b%s\b" % (re.escape(my_word),))
好了,既然这些问题都解决了,这里有一个方法可以用来实现你想要的功能:
value = "this is my super duper testing thingy"
keywords = "super|my|test"
from django.utils import html
import re
# first we must split up the keywords
keywords = keywords.split("|")
# Next we must make each keyword safe for use in a regular expression,
# this is similar to the HTML escaping we discussed above but not to
# be confused with it.
keywords = [re.escape(k) for k in keywords]
# Now we reform the keywordTags string, but this time we know each keyword is regexp-safe
keywords = "|".join(keywords)
# Finally we create a regular expression that matches *any* of the keywords
keywordMatcher = re.compile(r'\b(%s)\b' % (keywords,))
# We are going to make the value into HTML (by adding <b> tags) so must first escape it
value = html.escape(value)
# We can then apply the regular expression to the value. We use a "back reference" `\0` to say
# that each keyword found should be replace with itself wrapped in a <b> tag
value = keywordMatcher.sub(r"<b>\1</b>", value)
print value
我强烈建议你花时间去理解这个方法的作用,否则你会陷入麻烦!虽然直接复制粘贴然后继续前进看起来更简单,但这会导致糟糕的代码,最糟糕的是你自己不会进步,也不会学习。所有优秀的程序员都是从初学者开始的,他们花时间去理解事物 :)