【问题标题】:Validate inlines before saving model在保存模型之前验证内联
【发布时间】:2012-02-09 17:29:35
【问题描述】:

假设我有这两个模型:

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

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

我使用简单的TabularInlineDistribution 管理表单中显示Components:

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

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

因此,我的目标是在保存之前验证 Distribution 的所有 Components 的百分比是否为 100。听起来很简单,所以我做了:

# ... 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%')

但这永远不会起作用,因为在Django中,所有对象都是在保存其外键或many2many相关对象之前保存的,这不是缺陷,它有一个原因:它不能先保存相关对象,因为对象它们相关的尚未定义ididNone,直到对象第一次保存在数据库中)。

我确定我不是第一个遇到这个问题的人。那么,有没有办法完成我想要做的事情?我在想也许是使用TabularInlineModelAdmin 的管理员黑客...?

【问题讨论】:

    标签: python django foreign-keys


    【解决方案1】:

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

    子类 BaseInlineFormSet 并重写 clean 方法以检查百分比的总和。

    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%')
    

    然后在ComponentInline 中使用您的内联表单集。

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

    【讨论】:

    • 这是个好主意!我知道内联有很多东西可以提供。我要试试这个权利知道
    • 太棒了!它与一些更改工作得很好。谢谢,真的:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-26
    • 2013-01-11
    • 1970-01-01
    • 1970-01-01
    • 2019-08-22
    • 1970-01-01
    相关资源
    最近更新 更多