Handling multiple related objects in the admin without using inlines

Thanks to @charettes and @KenWhitesell for the pointers that have got me further than I expected in my custom admin quest.

Where I have got so far

I have a Project model, and a ProjectObjectConditions model that has a ForeignKey to it (the actual models (on Github)):

class Project(models.Model):
    [...]

class ProjectObjectiveCondition(models.Model):
    project = models.ForeignKey(Project, on_delete=models.CASCADE)

With a custom inline admin template (on Github), the inlines look like this:

What you are seeing there is:

  • Objective: Agreeableness
    • Level: Started
      • Condition: Speaks pleasantly
      • Condition: Doesn’t shout
    • Level: First results
      • Condition: Accepts thanks with gracce
    • Level: Mature results
      • Condition: Apologises with sincerity
  • Objective: Colourfulness
    • Level: Started
      • Condition: Has blue
      • … and so on

The Conditions are grouped (thanks to @KenWhitesell for the pointers) by Objective and Level through repeated use of {% regroup %} in the template.

Date/commitment columns

You can also see columns for the dates (instances of the WorkCycle class) and their True/False values, that show whether a commitment was made for this Project, and to reach which Level, in which WorkCycle (i.e. in which year).

I want to replace those with editable tick-boxes.

I actually have another inline, LevelCommitmentInline, which allows me to edit those True/False values for that model - but I don’t want them in a long list somewhere else, I want to see each one against the Objective and Level it is associated with, and under the date columns - right here.

How to do it

I think I will need to generate multiple forms to do this, one for each Objective/Level of the Project, for each WorkCycle. And then I will need to find a way to attach each of those forms to something - but I don’t know what.

The Objective and Level objects in this template, which they need to be associated with in the admin page, don’t actually come from the form, they are extracted by using {% regroup %}.

Any bright ideas?