In the past month, I have written a webcomponent, which encapsulates most of the functionality the Django admin's change view implements. It is very Pythonic/Djangonic in the sense, that it does not require to write any JavaScript, nor HTML. You can just use your Django Form as usual, warp it inside that component <django-formset>...</django-formset> and use a slightly modified Django View.
Here is a list of additional features: - Before submitting, our Form is prevalidated by the browser, using the constraints we defined for each Django Field. - The Form's data is send by an Ajax request, preventing a full page reload. This gives a much better user experience. - Server side validation errors are sent back to the browser, and rendered near the offending Form Field. - Non-field validation errors are renderer together with the form. - CSRF-tokens are handled through a Cookie, hence there is no need to add that token to each form. - Forms can be rendered for different CSS frameworks using their specific style-guides for arranging HTML. Currently *django-formset* includes renderers for Bootstrap <https://getbootstrap.com/docs/5.0/forms/overview/>, Bulma <https://bulma.io/documentation/form/general/>, Foundation <https://get.foundation/sites/docs/forms.html>, Tailwind <https://tailwindcss.com/> 1 <https://github.com/jrief/django-formset#user-content-fn-1-2e943bcba47ba2105e8752cfb8d2cfbe> and UIKit <https://getuikit.com/docs/form>. - Support for all standard widgets Django currently offers. This also includes radio buttons and multiple checkboxes with options. - File uploads are handled asynchronously. This means that the user opens the file dialog or drags a file to the form. This file then is uploaded immediately to a temporary folder, returning a unique handle together with a thumbnail of it. On form submission, this handle then is used to access that file and proceeds as usual. - Select boxes with too many entries, can be filtered by the server using a search query. No extra endpoint is required for this feature. - Radio buttons and multiple checkboxes with only a few fields can be rendered inlined rather than beneath each other. - The Submit buttons can be configured as a chain of actions. It for instance is possible to change the CSS depending on success or failure, add delays and specify the further proceedings. This for instance allows to specify the success page in HTML rather than in the Django View. - A Formset can group multiple Forms into a collection. On submission, this collection then is sent to the server as a group a separate entities. After all Forms have been validated, the submitted data is provided as a nested Python dictionary. - Such a Form-Collection can be declared to have many Form entities of the same kind. This allows to create siblings of Forms, similar the Django's Admin Inline Forms. However, each of these siblings can contain other Form-Collections, which themselves can also be declared as siblings. This list of siblings can be extended or reduced using one "Add" and multiple "Remove" buttons. - By using the special attributes show-if="condition", hide-if="condition" or disable-if="condition" on input fields or fieldsets, one can hide or disable these marked fields. This condition can evaluate all field values of the current Formset by a Boolean expression. - The client part, has no dependencies to any JavaScript-framework. It is written in pure TypeScript and compiles to a single, portable JS-file. That library only runs with Django>=4 and will be announced together when Django-4.0 will be released. A working prototype can be found here: https://github.com/jrief/django-formset – Jacob -- You received this message because you are subscribed to the Google Groups "Django developers (Contributions to Django itself)" group. To unsubscribe from this group and stop receiving emails from it, send an email to django-developers+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/django-developers/60ec115e-3aba-47d5-9a2b-f4f22ab21412n%40googlegroups.com.