我正在使用Django 1.4,并且我想设置比较不同内容的值的验证规则.
我有三个简单的课
在models.py中
class Shopping(models.Model): shop_name = models.CharField(max_length=200) class Item(models.Model): item_name = models.CharField(max_length=200) cost = models.IntegerField() item_shop = models.ForeignKey(Shopping) class Buyer(models.Model): buyer_name = models.CharField(max_length=200) amount = models.IntegerField() buyer_shop = models.ForeignKey(Shopping)
在admin.py中
class ItemInline(admin.TabularInline): model = Item class BuyerInline(admin.TabularInline): model = Buyer class ShoppingAdmin(admin.ModelAdmin): inlines = (ItemInline,BuyerInline)
所以例如可以买到一瓶10毫升的黄金和一个伏特加8美元.麦克支付15美元,汤姆支付3美元.
目标是防止用户以不匹配的金额存储实例:已支付的内容必须与项目成本的总和相同(即10 8 = 15 3).
我试过了:
>在Shopping.clean方法中提高ValidationError.但是内联没有更新,但没有更新,所以总和是不正确的
>在ShoppingAdmin.save_related方法中提高ValidationError.但是提高ValidationError这里给出了一个非常用户不友好的错误页面,而不是重定向到一个漂亮的错误消息的更改页面.
有没有解决这个问题?客户端(javascript / ajax)验证最简单?
解决方法
你可以覆盖你的Inline formset来实现你想要的.在表单集的干净方法中,您可以通过“实例”成员访问您的购物实例.因此,您可以使用购物模型临时存储计算总额,并使您的表单通信.在models.py中
class Shopping(models.Model): shop_name = models.CharField(max_length=200) def __init__(self,*args,**kwargs) super(Shopping,self).__init__(*args,**kwargs) self.__total__ = None
在admin.py中
from django.forms.models import BaseInlineFormSet class ItemInlineFormSet(BaseInlineFormSet): def clean(self): super(ItemInlineFormSet,self).clean() total = 0 for form in self.forms: if not form.is_valid(): return #other errors exist,so don't bother if form.cleaned_data and not form.cleaned_data.get('DELETE'): total += form.cleaned_data['cost'] self.instance.__total__ = total class BuyerInlineFormSet(BaseInlineFormSet): def clean(self): super(BuyerInlineFormSet,so don't bother if form.cleaned_data and not form.cleaned_data.get('DELETE'): total += form.cleaned_data['cost'] #compare only if Item inline forms were clean as well if self.instance.__total__ is not None and self.instance.__total__ != total: raise ValidationError('Oops!') class ItemInline(admin.TabularInline): model = Item formset = ItemInlineFormSet class BuyerInline(admin.TabularInline): model = Buyer formset = BuyerInlineFormSet
这是唯一可以做到这一点的干净的方式(据我所知),一切都放在了应有的地方.
编辑:添加*如果form.cleaned_data *检查,因为窗体包含空的内联.
请让我知道这对你有用吗