Opened 14 months ago

Last modified 10 months ago

#26142 assigned New feature

Provide a way for model formsets to disallow new object creation

Reported by: Tim Graham Owned by: Mathias Rav
Component: Forms Version: master
Severity: Normal Keywords:
Cc: Triage Stage: Accepted
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no


Model formsets don't provide a way to create an "edit only" view of objects. We see users trying to use extra=0 to accomplish this, but that's not reliable as extra is merely meant for the extra number of forms to display. You can add more forms with Javascript (or just send additional post data).

Attachments (1)

26142-test.diff (1.2 KB) - added by Tim Graham 10 months ago.

Download all attachments as: .zip

Change History (8)

comment:1 Changed 14 months ago by Tim Graham <timograham@…>

In 8e6a08e:

Refs #26142 -- Documented that Formset's extra=0 doesn't prevent creating objects.

comment:2 Changed 14 months ago by Tim Graham <timograham@…>

In 204d31c:

[1.9.x] Refs #26142 -- Documented that Formset's extra=0 doesn't prevent creating objects.

Backport of 8e6a08e937272f088902cdbec65a9f2e919783bf from master

comment:3 Changed 14 months ago by Mathias Rav

Owner: changed from nobody to Mathias Rav
Status: newassigned

comment:4 Changed 11 months ago by David Sanders

Doesn't max_num already allow this? Testing on master, if you have max_num set to 0 and validate_max to True, then the formset is effectively edit-only for existing objects. From the documentation:

max_num does not prevent existing objects from being displayed

Is there a corner case of functionality that's not covered by these two settings?

comment:5 Changed 11 months ago by Tim Graham

Yes, I think it's that sending data that references pks that don't appear in the queryset creates new objects for that data.

comment:6 Changed 11 months ago by David Sanders

Can you expand on that a little? Looking at the formset code, if the form number is less than the initial form count, it uses save_existing_object. Since validate_max prevents any forms above initial form count from being a valid formset, the only way a new object could be created is if save_existing_object could create new objects, which would be a bug in itself probably.

Playing with it in Chrome, providing a blank value for the PK of one of the objects in the formset will cause an error when trying to use to_python on the PK value since the value is blank and an integer is expected. Even if that didn't fail, it would fail to find the object by its PK in the queryset.

Providing a bogus value for the PK will also fail to look up in the queryset on the formset. This also occurs if you use a PK for an existing object that isn't in the queryset, which is good, otherwise you'd be able to modify objects outside the queryset which would be very bad.

So, I'm not sure I see the path where new objects can be created if validate_max is set and max_num is 0. Doesn't mean it's not there, but it's not immediately obvious how that could occur.

comment:7 Changed 10 months ago by Tim Graham

I don't think max_num=0 allows editing existing instances. Such a formset will fail with "Please submit 0 or fewer forms." won't it?

The idea I had to try to accomplish this is setting max_num=len(queryset) but I'm attaching a regression test demonstrating that an extra instance is created if the user edits the 'form-INITIAL_FORMS' form value.

Changed 10 months ago by Tim Graham

Attachment: 26142-test.diff added
Note: See TracTickets for help on using tickets.
Back to Top