At a loss with nested, dynamic forms.

I’m brand new to Django, and a novice coder. I’m trying to figure out the Django way to do this:

This simple app allows a user to create a Gradeslip to grade a student on a predefined set of Skills. The skills are grouped by SkillCatgory. The Students, Skill, and SkillCategories are already in the database. I don’t want the user to be able to add/modify/delete the Students, Skills, or SkillCategories, just assign a grade to each skill when a new Gradeslip is created.

What the user should see is a page that selects the student, presents (in text) each skill (grouped by SkillCategory), and a form field to input a grade.

I feel like inline formsets are a part of the equation, but I don’t know that for sure. All of the examples I can find are a bit more simple than what I’m trying to do here. I feel like there are three things adding to my confusion:

  1. Gradeslip and multiple SkillEvaluations need to all be created and associated at the same time.

  2. SkillEvaluations have a FK to Skills (which has a FK to SkillCatgories), and neither Skills or SkillCategories should be created/modified by the user.

  3. the user interface needs to have the Skills organized and labeled by SkillCategory.

Can someone please point me in a direction to go?

UML attached.

uml

Rephrasing this to ensure I understand the requirement.

You effectively have a Many-to-many relationship between GradeSlip and Skill, with SkillEvaluation as the “through” model.

An individual GradeSlip is related to one Student. A Student can be related to many GradeSlip.

A Skill is related to one SkillCategory. A SkillCategory can be related to many Skill.

Sequence of events - and this is where I think I’m confused:

What defines which SkillEvaluation instances need to be created?

Since it appears that the grade is the only element being entered here, there’s no need for a nested anything. A simple formset on the SkillEvaluation is all that’s required. The visualization (rendering) of part of the formset based on SkillCategory is a templating issue and not a structural issue affecting the formset.

So, to address your specific numbered comments:

Ok. This does not add any real complexity to the requirements.

It’s always easier to not-do something than to do something. Not editing Skill or SkillCategory makes this an easier task.

This is a templating issue and only affects the code in that it requires the list of Skill to be associated with the grade be sorted by SkillCategory. Again, does not materially affect the complexity here.

In general then, if I know what the criteria are for selecting the list of Skill to be referenced, I’d create a ModelFormset, initialized where each instance of the form is referencing the properly-sorted entry of Skill. The gradeslip FK can be ignored at this point. (You do not need to even reference this field in the form.) This formset gets rendered to the page however you wish.

Then, on the post, when you bind the data, you verify the form as being valid. If it is valid, you create an instance of GradeSlip, assign the pk of that new GradeSlip to the gradeslip field in the individual entries of the formset and save the instance.

Thank you kindly for responding!

You’re understanding of the relationships is correct. I’ve attached another image to better explain what I’m trying to accomplish, as well.

Every Skill stored in the database needs to be on the page the user sees, so there would be one SkillEvaluation instance (per Gradeslip) for each Skill that exists in the database.

I want the user to have a dropdown to select the Student (which is a FK in Gradeslip), so don’t I need to insantiate both a Gradeslip, and one SkillEvaluation per Skill, and somehow associate those SkillEvaluations to the the Gradeslip, prior to presenting the template to the user?

Nope, because you don’t need to have (or have) that information at the time the initial formset is presented. All you need to have is the Student’s name and the list of Skills to which grades will be assigned. The creation of those objects doesn’t need to occur until the grades are submitted.

Supplemental: You can create those entries in advance, but all you’re really doing is moving that work from the POST portion of the view to the GET. (It doesn’t save any work and it doesn’t reduce the amount of code needed - it only changes where that work gets performed.)

Thanks! I’ll keep plugging away at it. I’m realizing that I’m in way over my head here. This is the first thing I’m trying to build with Django, and my first time building something with an MVC philosophy. Last time I coded regularly was a long time ago, building web apps procedurally with MS-SQL and ASP (not ASP.net). I’ve got a steep learning curve to climb up.

As far as the SkillEvaluation objects in the formset, do I create those for the GET without associating them to their respective SkillCategories? Or is there a way to fill up the formset with SkillEvaluation objects that are already linked to their SkillCategories?

You first need to decide which of the two approaches you will take:

  1. Don’t create any new objects until the forms are submitted.

  2. Create the SkillEvaluation object and the set of GradeSlip objects before creating and displaying the form

Side note: Django’s architectural pattern (MVC or MTV - see FAQ: General | Django documentation | Django) really isn’t an issue or a factor here. What’s important to understand is the common flow of working with forms and understanding the difference between bound and unbound forms.