The Python Oracle

How do I change the widget type of the DELETE field in a django formset

Become part of the top 3% of the developers by applying to Toptal https://topt.al/25cXVn

--

Music by Eric Matyas
https://www.soundimage.org
Track title: Magic Ocean Looping

--

Chapters
00:00 Question
01:29 Accepted answer (Score 11)
02:13 Answer 2 (Score 26)
03:01 Answer 3 (Score 1)
03:18 Thank you

--

Full question
https://stackoverflow.com/questions/9379...

Answer 1 links:
https://docs.djangoproject.com/en/1.4/to...
[definition of DELETION_FIELD_NAME]: https://github.com/django/django/blob/1....
[definition of add_fields() method]: https://github.com/django/django/blob/1....
[the place in which add_field() is called - after a form is constructed, so you cannot do anything in Form.]: https://github.com/django/django/blob/1....

--

Content licensed under CC BY-SA
https://meta.stackexchange.com/help/lice...

--

Tags
#python #django

#avk47



ANSWER 1

Score 27


The shortest code to accomplish what you need is:

class MyFormSet(BaseFormSet):
    def add_fields(self, form, index):
        super(MyFormSet, self).add_fields(form, index)
        form.fields[DELETION_FIELD_NAME].widget = forms.HiddenInput()

It cannot be considered a hack because it's mentioned in the official Django docs:

https://docs.djangoproject.com/en/1.4/topics/forms/formsets/#adding-additional-fields-to-a-formset

Django sources to read:




ACCEPTED ANSWER

Score 11


It doesn't change anything if your input is of type=hidden, or if it is of type=checkbox and display: none.

IMHO the elegant way in CSS would look like this:

td.delete input { display: none; }

Or in JavaScript:

$('td.delete input[type=checkbox]').hide()

Or, in the admin:

django.jQuery('td.delete input[type=checkbox]').hide()

That seems like a better direction to take because:

  1. It won't change your JavaScript code and
  2. It's one line of code vs. so much Python hacks



ANSWER 3

Score 1


Setting self.can_delete to False solved my problem:

class MyFormSet(BaseFormSet): 
    def __init__(self, *args, **kwargs): 
        super(MyFormSet, self).__init__(*args, **kwargs) 
        self.can_delete = False 



ANSWER 4

Score 0


You can also override the initializer in the FORMSET (NOT FORMS) class, because the DELETE field is created by the Formset.

class YourFormSet(BaseFormSet):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        for form in self.forms:
            form.fields["DELETE"].widget = YourWidget()