Django唯一约束+表单错误

7

我在我的网站上遇到了一些重复发布的问题。我认为在所有相关字段上设置一个简单的唯一约束将解决数据库级别的问题,但这只会为用户产生一个糟糕的错误页面。有没有办法将其转换为漂亮的表单错误呢?例如non_field_error?或者我应该采取什么方法呢?


如果您能接受一个答案,我非常想为这个问题点赞。 - raratiru
@raratiru 好的,如果这让你开心,我就选了一个 ;) 不确定那是否是我7年前实际采用的解决方案 -- 我通常会接受我最终使用的那个。 - mpen
其实,那就是我用的!:-D - raratiru
2个回答

14

也许这个可以帮到你:

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

    def clean(self):
        cleaned_data = self.cleaned_data
        your_unique_key = cleaned_data['your_unique_key']

        if your_unique_key and YourModel.objects.get(your_unique_key=your_unique_key):
            raise forms.ValidationError("not unique")

        # Always return the full collection of cleaned data.
        return cleaned_data

clean()方法允许您访问表单的所有字段,如果您有一个组合唯一键,则可能会有用。否则,使用(略短的)clean_your_unique_key()可能更适合您。

请注意,在极少数情况下(竞争条件),表单验证可能不会报告重复条目(但数据库引擎当然会报告)。但对于大多数应用程序而言,提供的示例将是更简单且更易于维护的方法,因此我仍然推荐使用这种方法。


1

关于用户的“错误页面”,Django允许您自定义自己的500、404和可能的其他页面。有关一般信息:

为了充分利用Http404异常,您应该创建一个在引发404错误时显示的模板。此模板应命名为404.html,并位于您的模板树的顶层。

-- http://docs.djangoproject.com/en/dev/topics/http/views/

另一种不像tux21b的解决方案那样DRY,但对于一次性解决方案可能更容易理解的好方法是聪明地捕获错误。其中一种方法是甚至不必违反约束条件-一个简单的查询应该验证用户是否即将执行非法操作。

okToUpdate=MyModel.objects.filter(parameters=values...).count()  

if okToUpdate>0:  # an object already exists  
    errorExists=True  
    errors={customError:customMessage}  

...  

if errorExists:  
     return render_to_response(errors,'customErrorPage.html')  

else:  
    # return whatever you normally would return  

然后您可以使用render_to_response来呈现自定义错误页面。

(另一种方法是允许发生数据库违规,然后捕获该错误并执行相同的操作...我推测DB在处理异常时会承受稍微较少的压力,但您可以根据自己的喜好选择如何处理事情)。

JB


嗯...装扮500页并不能让它变得更好。它们仍然被带离了它们应该在的页面,实际上,这是误导性的,因为事实上他们的帖子中有一个确实通过了,所以它不是真正的“错误”,而更像是一个警告,如果它甚至值得成为那样的话。关于你的第二个解决方案...那也不是很好。它违反了DRY原则。这种东西真的应该在表单中,与验证发生在同一地方。 - mpen
我是泛泛而谈,可能并不是针对Django表单的特定用途。你确实将结果描述为“恶心的错误页面”。关于第二个想法打破DRY原则,我明确提到它不是DRY原则,而是一次性的。要使其可重用,您可以将其封装在一个可从任何地方调用的函数中。即def checkModelUpdateOk(anyModel,someParams,...):
okToUpdate=anyModel.complex_filter(someParams).count() (等等,返回错误消息或绿灯)...其中someParams是指定您要查找的键和值的字典(针对您的目标模型)。
  • J
- jsh
参数的数量几乎等于代码的长度 :) 无论如何,它们是有效的解决方案,只是不是首选。 - mpen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接