2014-02-12 62 views
0

我已经写在Django 1.6这个信号接收器,旨在从被保存的数据库阻止包含脏话发表的评论:如何告诉django不要在数据库中保存实例?

@receiver(pre_save, sender= Comment) 
def spam_filter(sender, **kwargs): 
    cmnt = kwargs['instance'] 
    my_expression = '|'.join(re.escape(word) for word in BAD_WORDS) 

    if re.search(my_expression, cmnt.body, flags=re.IGNORECASE):  
     #pervent the comment from being saved 


    else: 
     pass 

我想知道如何告诉Django代替“#pervent评论得救”不保存'坏'评论实例?

P.S.该教职员:

@login_required 
def add_comment(request, post_id): 

    p= Blog.objects.get(id=post_id) 
    post_slug = p.slug 
    cform = CommentForm(request.POST) 
    if cform.is_valid(): 
     c = cform.save(commit = False) 
     c.created = timezone.now() 
     c.post = p 
     c.author = request.user 
     c.save() 
     args=post_slug 
     messages.info(request, "comment was added") 
     return HttpResponseRedirect(reverse("Blog.views.post_withslug", 
              args=[post_slug])) 
+0

为什么选择使用信号而不是在清洁表单域时编写该逻辑? –

+0

@ScottWoodall我是django的新手,你提出了一个很好的问题。使用信号代替集成到视图中有很多开销吗?如果是这样,我会修改代码。 – supermario

回答

4

根据您的是新的Django我评论将提供一种替代解决方案。尝试在表单验证过程中查找错误的单词。您可以按照以下格式检查writing a method for a specific field的特定表单字段:def clean_<fieldname>。如果您CommentForm有一个字段名body我们可以做到以下几点:

from django import forms 

class CommentForm(forms.Form): 
    # Everything as before. 
    ... 

    def clean_body(self): 
     body = self.cleaned_data['body'] 
     my_expression = '|'.join(re.escape(word) for word in BAD_WORDS) 

     if re.search(my_expression, body, flags=re.IGNORECASE):  
      # prevent the comment from being saved 
      raise forms.ValidationError("Wash your mouth out with soap.") 

     # Always return the cleaned data, whether you have changed it or 
     # not. 
     return body 

编辑:

看到你的观点后,一些补充意见。

您应该可以将def clean_body()函数添加到CommentForm,并使其表现符合预期。您发布的视图只会在form.is_valid()评估为True时回应。您需要确保视图可以处理,如果有人评论包含一个不好的单词,form.is_valid评估为False。请参阅示例代码here for a typical Django function based view。如果在解决这些问题后,您仍然遇到问题,例如CommentForm和模板代码以及任何异常。务必删除您的原始信号代码。

p = Blog.objects.get(id=post_id)替换为p = get_object_or_404(Blog, pk=post_id)。这样,如果用户提供了不好的post_id,他们将立即得到404而不是抛出异常,因为get()将无法​​找到单个对象。有关get_object_or_404here的文档。

您还可以通过创建时,有你的模型automatically add the current time节省几行:

class Comment(models.Model): 
    created = models.DateField(auto_add_now=True) 

然后你可以从视图中删除c.created = timezone.now()

+0

这看起来很清晰。最后一行应该是“返回主体”。此外,我想打印出一条消息给用户,该评论包含坏词。我如何添加这个? – supermario

+0

用户可以看到“用肥皂清洗你的嘴”这一行,显然可以根据自己的喜好改变它。发布您查看代码,我可以进一步帮助您了解如何使用上述代码。 –

+0

添加了视图。谢谢 – supermario

1

我认为你可以提高在

try: 
    MyModel.objects.save() #or create 
except ValidationError: 
    do_other_staff 

一些例外,赶上在代码:

if not re.search(my_expression, cmnt.body, flags=re.IGNORECASE): 
    return True 

raise ValidationError('this text explains an error') 
+0

你会详细说明这个尝试/除了如何集成到我的代码的条件? – supermario

+0

@supermario更新回答 –

+0

这在调试模式下工作,谢谢。只是想知道在这种例外情况下生产模式会发生什么? – supermario

相关问题