我在我的网站上遇到了一些重复发布的问题。我认为在所有相关字段上设置一个简单的唯一约束将解决数据库级别的问题,但这只会为用户产生一个糟糕的错误页面。有没有办法将其转换为漂亮的表单错误呢?例如non_field_error
?或者我应该采取什么方法呢?
我在我的网站上遇到了一些重复发布的问题。我认为在所有相关字段上设置一个简单的唯一约束将解决数据库级别的问题,但这只会为用户产生一个糟糕的错误页面。有没有办法将其转换为漂亮的表单错误呢?例如non_field_error
?或者我应该采取什么方法呢?
也许这个可以帮到你:
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()
可能更适合您。
请注意,在极少数情况下(竞争条件),表单验证可能不会报告重复条目(但数据库引擎当然会报告)。但对于大多数应用程序而言,提供的示例将是更简单且更易于维护的方法,因此我仍然推荐使用这种方法。
关于用户的“错误页面”,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