Complex form validation

Hi there!
I’m developing an app, utilizing the built-in admin interface, that tracks invoices.

  • Each invoice object has a value.
  • Invoices have child Bank statements (bank statement → invoice one to one)
  • invoices have child invoice items (invoice item → invoice one to one)

Both the bank statement and invoice item objects also have a value.

I already have an admin form with tabular inlines. What I’m trying to do now is, when a invoice form is submitted and before committing any changes to the db, I want to sum the values of the relevant bank statements and invoice items. If either of the sums don’t match the invoice value I want to display an error to the user.

How could I achieve this?
Thanks for your help!

Welcome @valentin-buick !

I’d first like to point out the first two paragraphs of The Django admin site docs:

From the first paragraph:

The admin’s recommended use is limited to an organization’s internal management tool. It’s not intended for building your entire front end around.

And in the second paragraph:

If you need to provide a more process-centric interface that abstracts away the implementation details of database tables and fields, then it’s probably time to write your own views.

My suggestion is to stop using the admin at this point, do what the documentation tells you to do and write your own views for this.

Thank you for the suggestion, however I’d really like to continue using the admin interface. This validation is the last thing I need to complete, the rest is already completely implemented. My goal was to get this up and running fairly quickly. So if you have any implementation suggestions (I’m not above hacking this together) I’d love to hear them!

I think I actually figured out a solution, at least this seems to be working!
What I did:

  • override clean method of the individual formsets, calculate the sum in there by iterating through self.forms
  • access parent form value inside that clean method using self.instance.value
  • do the comparison in there and throw an error

Hope this helps someone!