Python 用户在Django表单中输入的无效正则表达式导致500服务器错误

Python 用户在Django表单中输入的无效正则表达式导致500服务器错误,python,regex,django,forms,Python,Regex,Django,Forms,我在我的web应用程序中设置了一个简单的Django搜索表单,用户可以在我的阿拉伯语语料库中搜索特定的单词。用户可以通过以下三种方式之一进行搜索:“精确”(即键入的单词)、“干”(显示输入的引理的所有屈折形式)和“正则表达式”(通过正则表达式可以进行更复杂的搜索) 我遇到的问题是,如果用户提交一个无效的正则表达式,而不是给他们一个验证错误或空结果,它会触发一个500服务器错误。我想这是令人困惑的。下面是由于搜索带有不平衡括号的正则表达式而导致的此类和错误的回溯:ha((.*(!al)) 是否有任

我在我的web应用程序中设置了一个简单的Django搜索表单,用户可以在我的阿拉伯语语料库中搜索特定的单词。用户可以通过以下三种方式之一进行搜索:“精确”(即键入的单词)、“干”(显示输入的引理的所有屈折形式)和“正则表达式”(通过正则表达式可以进行更复杂的搜索)

我遇到的问题是,如果用户提交一个无效的正则表达式,而不是给他们一个验证错误或空结果,它会触发一个500服务器错误。我想这是令人困惑的。下面是由于搜索带有不平衡括号的正则表达式而导致的此类和错误的回溯:ha((.*(!al))

是否有任何方法可以捕获此类错误,或使其更易于使用?(我还在下面的表单中包含了代码。)

多谢各位

class ConcordanceForm(forms.Form):
    searchterm = forms.CharField(max_length=100, required=True)
    search_type = forms.ChoiceField(widget=RadioSelect(), 
             choices= ([('string', 'Exact'), ('lemma', 'Stem'), ('regex', 'Regex') ]),
             required=True )


def concord_test(request):  
    if request.method == 'POST': 
        form = ConcordanceForm(request.POST)
        if form.is_valid(): 
            searchterm = form.cleaned_data['searchterm'].encode('utf-8')
            search_type = form.cleaned_data['search_type']
            context, texts_len, results_len = make_concordance(searchterm, search_type)
            return render_to_response('corpus/concord.html', locals())
    else:
        form = ConcordanceForm()
    return render_to_response('corpus/search_test.html', 
                              {'form': form}, context_instance=RequestContext(request))



<p style=" font-weight:bold;">Search for any word in the corpus:</p>
<form action="/search_test/" method="post">{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Submit" />
</form>
class ConcordanceForm(forms.Form):
searchterm=forms.CharField(最大长度=100,必需=True)
search_type=forms.ChoiceField(widget=RadioSelect(),
选项=([('string','Exact'),('lemma','Stem'),('regex','regex')),
必需=真)
def concord_测试(请求):
如果request.method==“POST”:
表单=一致性表单(request.POST)
如果form.is_有效():
searchterm=form.cleaned_数据['searchterm'].编码('utf-8')
搜索类型=表单。已清理的数据['search\u type']
上下文、文本、结果=一致性(搜索词、搜索类型)
返回render\u to\u响应('corpus/concord.html',locals())
其他:
form=一致性form()
返回render\u to\u response('corpus/search\u test.html',
{'form':form},context_instance=RequestContext(请求))
在语料库中搜索任何单词:

{%csrf_令牌%} {{form.as_p}}
回溯(最近一次呼叫最后一次):

get_响应中的第100行“
File”/home/larapsodia/webapps/django/lib/python2.6/django/core/handlers/base.py”
响应=回调(请求,*回调参数,**回调参数)
文件“/home/larapsodia/webapps/django/tunisiya2/corpus/views.py”,第154行,在concord_测试中
上下文、文本、结果=一致性(搜索词、搜索类型)
文件“/home/larapsodia/webapps/django/tunisiya2/corpus/views.py”,第91行,在make_concordance中
p=re.compile(r'\b'+searchterm+r''uu')#单词的初始位置(位置)引理字符串
文件“/usr/local/lib/python2.6/re.py”,第190行,编译
返回编译(模式、标志)
文件“/usr/local/lib/python2.6/re.py”,第245行,在编译中
raise错误,v#表达式无效
错误:不平衡括号

使一致性
包装在
尝试中
-
除外
;如果发生异常, 为用户呈现原始表单模板以及错误信息

import re
try:
    context, texts_len, results_len = make_concordance(searchterm, search_type)
except re.error as e:
    form._errors['search_term'] = str(e)
    del form.cleaned_data['search_term']

    return render_to_response('corpus/search_test.html', 
         {'form': form}, context_instance=RequestContext(request))


更好的方法可能是创建一个,但它似乎有点复杂,而且我没有Django。

根据@Sam的注释,下面介绍如何在正则表达式无法编译时捕获特定错误:

import re
err_message = None
try:
    re.compile('(unbalanced')
except re.error as exc:
    err_message = 'Uhoh: {}'.format(exc)

print err_message
输出:

不平衡括号


正如Antti所提到的,我最终建立了一个定制的清洁器。这就是最终的效果:

def clean(self):
    cleaned_data = self.cleaned_data
    searchterm = cleaned_data.get('searchterm')
    search_type = cleaned_data.get('search_type')
    if search_type == 'regex':
        try:
            re.search(searchterm, 'randomdatastring') #this is just to test if the regex is valid
        except re.error:
            raise forms.ValidationError("Invalid regular expression.")
    return cleaned_data

看起来您需要仔细阅读。在这种情况下,您可能希望捕获错误“人性化”(即说“输入了无效表达式”),并返回一个没有结果和错误的页面。谢谢你,安蒂,我想这正是我需要的。我在实现第二个解决方案时遇到了问题,所以我刚刚添加了try/except,它可以工作!如果我输入了无效的正则表达式,它将留在表单上,而不是试图处理它并返回服务器错误。我仍然有一个问题:怎么办在您编写“#将str(e)作为错误报告给用户”的空间中。如何在表单上显示错误消息?(对不起,我知道这可能很明显,但我对表单的使用不是很有经验。)第二种解决方案有什么问题?它应该很容易自动向用户显示错误。有很多问题。我花了大约半个小时一个接一个地解决它们,但当我遇到以下问题时放弃了:文件“/home/larapsodia/webapps/django/tunisiya2/corpus/models.py”,第25行,在clean_searchterm self.clean_data['search_type')KeyError:“search_type”我认为第一个对我来说更好,因为它更简单,我对它有更好的理解。你能告诉我如何将错误消息传递到表单吗?谢谢。我正试图用这种方式捕获异常,但我对你的解决方案(以及引用的文档)有问题我不是在命令行上这样做的:我需要知道如何将错误消息返回到表单。
def clean(self):
    cleaned_data = self.cleaned_data
    searchterm = cleaned_data.get('searchterm')
    search_type = cleaned_data.get('search_type')
    if search_type == 'regex':
        try:
            re.search(searchterm, 'randomdatastring') #this is just to test if the regex is valid
        except re.error:
            raise forms.ValidationError("Invalid regular expression.")
    return cleaned_data