保存模型前验证内联 [英] Validate inlines before saving model

查看:102
本文介绍了保存模型前验证内联的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我有这两个模型:

  class Distribution(models.Model):
name = models .CharField(max_length = 32)

class组件(models.Model):
distribution = models.ForeignKey(Distribution)
percent = models.IntegerField()

我正在使用一个简单的 TabularInline 来显示组件分发管理表单中:

  class ComponentInline(admin.TabularInline):
model = Component
extra = 1

class DistributionAdmin(admin.ModelAdmin):
inlines = [ComponentInline]

所以,我的目标是验证所有 分配组件之前保存100。听起来很简单,所以我做了:

 #...分配模型内
def clean(self):
#组件总和必须为100
total_sum = sum(comp.percentage for comp in self.component_set.all())
如果total_sum!= 100:
raise ValidationError('组件总和必须为100%')

但是这不会工作,因为在Django中所有对象在保存其外键或许多2个相关对象之前被保存,这不是缺陷,它有一个原因:它不能先保存相关对象,因为它们相关的对象没有一个 id 定义( id 直到对象第一次保存在DB中)



我相信我不是第一个遇到这个问题的人。那么,有没有办法完成我想要做的事情?我正在考虑使用 TabularInline ModelAdmin ...?

解决方案

这是一个(未经测试)的想法,如果您很乐意将验证从模型移动到内联表单集:



子类 BaseInlineFormSet 并覆盖clean方法来检查百分比之和。

导入BaseInlineFormSet
from django.core.exceptions import ValidationError

class ComponentInlineFormSet(BaseInlineFormSet):

def clean(self):
检查组件的总和是否为100%
如果有的话(self.errors):
#不要打扰验证表单,除非每个表单对于self.forms中的表单,
返回
total_sum = sum(form.cleaned_data ['percentage'])
如果total_sum!= 100:
raise ValidationError( 组件总和必须是100%')

然后在 ComponentInline

  class ComponentInline(admin.TabularInline):
model = Component
extra = 1
formset = ComponentInlineFormSet


Let's say I have these two models:

class Distribution(models.Model):
    name = models.CharField(max_length=32)

class Component(models.Model):
    distribution = models.ForeignKey(Distribution)
    percentage = models.IntegerField()

And I'm using a simple TabularInline to show Components inside the Distribution admin form:

class ComponentInline(admin.TabularInline):
    model = Component
    extra = 1

class DistributionAdmin(admin.ModelAdmin):
    inlines = [ComponentInline]

So, my goal is to validate if the percentages of all the Components of the Distribution sum 100 before saving it. Sounds simple, so I did:

# ... Inside the Distribution model
def clean(self):
    # Sum of components must be 100
    total_sum = sum(comp.percentage for comp in self.component_set.all())
    if total_sum != 100:
        raise ValidationError('Sum of components must be 100%')

But this will never work work, because in Django all objects are saved before saving its foreign-key or many2many related objects, this is not a flaw, it has a reason: it cannot save the related objects first, because the object to which they are related doesn't have an id defined yet (id is None until the object is saved for the first time in the DB).

I'm sure I'm not the first guy to run into this issue. So, is there a way to accomplish what I'm trying to do? I was thinking maybe a admin hack using TabularInline or ModelAdmin ... ?

解决方案

Here's an (untested) idea, if you're happy to move the validation from the model to the inline formset:

Subclass BaseInlineFormSet and override the clean method to check the sum of the percentages.

from django.forms.models import BaseInlineFormSet
from django.core.exceptions import ValidationError

class ComponentInlineFormSet(BaseInlineFormSet):

    def clean(self):
        """Check that sum of components is 100%"""
        if any(self.errors):
            # Don't bother validating the formset unless each form is valid on its own
            return
        total_sum = sum(form.cleaned_data['percentage'] for form in self.forms)
        if total_sum != 100:
            raise ValidationError('Sum of components must be 100%')

Then use your inline formset in the ComponentInline.

class ComponentInline(admin.TabularInline):
    model = Component
    extra = 1
    formset = ComponentInlineFormSet

这篇关于保存模型前验证内联的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆