Django Admin - Custom clean method for a model with foreignkey field
django-1.4, django-admin, django-forms, django-models
Solution
Ok, I finally found a way.
Just to clarify, I want to validate that the sum of all sections' crowd capacity doesn't exceed total arena crowd capacity.
Final solution is (in admin.py):
class SectionFormSet(forms.models.BaseInlineFormSet):
def clean(self):
if any(self.errors):
return
capacity = 0
for f in self.forms:
try:
capacity += f.cleaned_data['crowd_capacity']
if capacity > f.cleaned_data['arena'].crowd_capacity:
raise ValidationError('The sum of all sections crowd capacity '
'exceeds arena crowd capacity')
except KeyError:
# in case of empty form
pass
class SectionInline(admin.StackedInline):
model = Section
formset = SectionFormSet
class ArenaAdmin(admin.ModelAdmin):
inlines = [
SectionInline,
]
Thats it, no change to models. Works like a charm :)
Problem
Consider following models: ``` class Arena(models.Model): crowd_capacity = models.PositiveInteger() # more fields here class Section(models.Model): name = models.CharField(max_length=10) crowd_capacity = models.PositiveInteger() arena = models.ForeignKey(Arena, related_name='sections') ``` admin.py : ``` class SectionInline(admin.StackedInline): model = Section fk_name = 'arena' extra = 1 class ArenaAdmin(admin.ModelAdmin): inlines = [ SectionInline, ] ``` I want to add a validation method to check that the sum of all section.crowd_capacity doesn't exceeds total arena.crowd_capacity. At first i wanted to write a custom SectionFormSet with clean method, but then i didn't see how to get arena.crowd_capacity. I also tried to add clean method to Arena, it does show a nice red validation error but doesn't let fix the problem. Looks like Arena clean method runs after all sections were saved, and changing section.crowd_capacity and w.e section had the problem has no effect. The validation method i tried: ``` def clean(self): super(Arena, self).clean() capacity = 0 for s in self.sections.all(): capacity += s.crowd_capacity if capacity > self.crowd_capacity: raise ValidationError('The sum of all sections crowd capacity ' 'exceeds arena crowd capacity') ```