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 Component
s 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 Component
s 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.Then use your inline formset in the
ComponentInline
.