python – 在django管理员中验证依赖内联

前端之家收集整理的这篇文章主要介绍了python – 在django管理员中验证依赖内联前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我正在使用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 *检查,因为窗体包含空的内联.
请让我知道这对你有用吗

EDIT2:添加了关于要删除的表单的检查,正如在评论中正确指出的那样.这些表格不应该参与计算.

猜你在找的Python相关文章