How to handle multiple DIFFERENT models with formsets?

Happy New Year!

I am tasked to create a template that conditionally needs to duplicate a form made of User table, Profile table, and Location table data. I THINK a formset could be ideal - but I have seen/read nothing on how to do a formset with aggregated forms using different models. One form would be for a Parent’s data and the other for the Reporter (an unrelated Reporter can call in a rescue - or the parent can. Both need the users name and contact info and address, if available). I know I can do one model form with formsets but can you do this with an aggregated ‘form’ made of several model forms? Should I instead create a DATABASE view of these separate models first and do a formset off the database view? If I did that would I create headaches if this eventually becomes a progressive web app with SQLite (local) and PostgresSQL (primary db on server)? Any examples/tutorials you know of? Other, better, options?

The specifics are: I have a Django view that allows volunteers to enter a Parent or a Reporter to describe a need to rescue a child. The only diff between a parent and a reporter is Reporter gets a boolean reporter flag set (initially schema was designed with one to many Parent to possibly many Children - but have considered a many to many so children can be associated with a parent and a Reporter). Names are in User, telephone and email are in Profile and physical address/latlong are in Location tables. The template has a set of the same fields for both Parent and Reporter but you check a ‘reporter’ checkbox if the info is from a Reporter. Only the Parent fields and an ‘Add Reporter’ button are visible initially. I have never actually implemented a formset yet…

Thanks in advance. Any insight appreciated.

I’m not sure I’m following you here - it almost looks to me like you’re asking a couple different questions.

Trying to approach this from a slightly different angle:

A formset is an abstraction layer to handle multiple instances of the same form. If you can create a form for whatever, you can create a formset to manage multiple instances of that form on a single page.

Forms can be created outside the context of a model. (In fact, a Model Form is just a special case of a form.)

So I’m getting the impression from what I’m able to understand here is that you might be looking to create a formset supporting a generic form that is suitable for either a Parent or Reporter. Then, when you’re processing that formset, you create & store the appropriate data type from each instance of the form.

Am I on the right track here, or am I missing something?

Let me try again with an image: I have a web page that copies a paper form used in real life. There are two sections of page with form parts with essentially identical fields; one for Reporter and the other for Parent. But they are composites made from fields from different model forms. Sometimes there is no known parent, only a reporter. Sometimes the parent is the reporter (so no Reporter section needs to be filled in). The yellow fields are from the User table/model (and UserForm), the blue from the Profile table/model (ProfileForm) and the pink from the Location table/model (LocationForm). So, the question is: can I do a formset to replicate these two sections and send the appropriate keys for the potentially 2 people associated with the children (Child table/model and ChildForm)? Or is there a better way? I have read, and you state, formsets are for replicating the SAME model form…if formsets simply cannot do this then would a model form based on a database view be a good solution? Would a many to many relationship and a corresponding Django view do this best?


Apologies to those with difficulty resolving colors…

Thanks!

The picture helps a little, but I’m still confused by what you’re saying.

It looks to me now that you shouldn’t be working with Model forms at all. Since you’re pulling (feeding?) data from (to) different Models, you may just want to use a form and do the association between the forms and their related models in your view.

Make sure you’re clear in your mind the difference between your models and your forms. Models are the representation of your data in your database. Forms are the representation of your data on a web page. When your web page closely aligns to your database, then ModelForms are appropriate. Otherwise, you want to manage those relationships yourself.

So I think when you are making references to ModelForms, you’re actually just talking about your models, correct?

Am I getting close?

Also for clarification:

Is wrong. Formsets are for replicating the same form, not necessarily the same model form.

Thanks for the clarification, I believe I know the distinction between models and forms and have been using modelforms to represent forms that interact with models and the database - which are all my forms currently. I imagine I could use ‘regular’ form.Forms and then use Modelname.objects.create() to manually assign form field values to the appropriate model and then save into the Db. Do people do that as standard practice? I was under the impression that for any form that does CRUD you really want to use modelforms. It seems unduly complex for this situation (not hard but sort of Rube Goldbergesque).

I think you are saying that
1: I cannot use formsets with form templates made of mutiple different modelforms - you can ONLY use them to duplicate a single form - whether it is a form.Form or modelform.
2: I CAN (and should likely here) create a form.Form type form similar to one of the multi-colored sections in the image, with ANY fields, as they have no connection to a model until I manually assign them to the model via the view.
3: Then I could replicate it as with a formset.
4: You are not suggesting better options yet, you have not weighed in on creating models or modelforms from database views or if this scenario is best handled in some other way/has some sort of Django design pattern.

Thanks for the input, I will consider using a ‘regular’ form with a formset.

Generally, yes - when the form doesn’t correlate closely to a model. I’ve got a couple of applications where there are few, if any, model forms at all.

When your form has a strict correlation to your model, it makes it easier to use a model form. But the “further away” your form is from your model, the more you’re going to find it easier to not try and wedge your process into a model form.

A model form is just an abstraction layer over a standard form that does some work for you. Whether you do the work or Django does the work doesn’t matter a whole lot.

You don’t create formsets from form templates. You create formsets from a form. (Not just model form.) The formset is created before any rendering is done with the template.

Correct. That’s what I was heading toward in the next-to-last paragraph of my earlier reply and the second paragraph of a subsequent reply.

Correct.

Correct, I was trying to make sure we’re clear on terminology and function.

Creating models mapping to database views works great - I’ve done a lot of that. (In my case, it’s always been for read-only, not read-write - but assuming your database engine allows for writable views it shouldn’t be a problem.) But you don’t create model forms from a database view - you create a model form from a model.

I’m not aware of alternative design patterns for addressing something like this.
My personal experience has been that Django is designed around the architecture that the database is built for Django and that you’re not trying to layer Django on top of a pre-existing database used for other applications. There are a couple of areas that create “friction” when trying to build a Django app on top of a database that was built outside of it.

1 Like

In doing a bit more digging into this, I found a (now-obsolete) package called django-betterforms that supports the creation of an abstraction layer called a MultiForm which is (quoting from their docs) “A container that allows you to treat multiple forms as one form.” (They also have a MultiModelForm for Model Forms.)

The package is essentially obsolete (2018, Django 2.0), but you could fork it to see if you wanted to work to bring it up-to-date.

Disclaimer - I am completely unfamiliar with this package, I know nothing about it beyond what I’m seeing in the docs on a cursory review.

As always: Thanks Ken. That was above and beyond in terms of patience. Over and over I see people referring to the ‘excellent’ documentation (I suspect for % coverage vs clear explanations) for Django, but I have found, for a beginner, they are less than that. Statements like: ‘When your form has a strict correlation to your model, it makes it easier to use a model form. But the “further away” your form is from your model, the more you’re going to find it easier to not try and wedge your process into a model form.’ are invaluable to a beginner because most tutorials are echoes of each other doing only the basics, and beginners do not know what is just an ugly hack vs a standard practice. Now you have blessed the pursuit of what I would have thought would be (and likely will be in MY hands…) an ugly hack. :wink:

1 Like

Just in case anyone else comes across this, there is a fork/pull-request for django-betterforms that updates the package for django 3.x.