Django forms: deleting forbidden fields is preserved between validations

At some point, I need to display the attribute "disabled" (greyed out by disabled="disabled" ) of type "select" . As indicated in the standard (xhtml and html4), inputs of type "select" cannot have the attribute "readonly" . Please note that this is for presentation purposes only, the actual value should end in POST. So here is what I am doing (quoting part of form declaration in django):

 from django import forms _choices = ['to be', 'not to be'] class SomeForm(forms.Form): field = forms.ChoiceField(choices=[(item, item) for item in _choices], widget=forms.HiddenInput()) # the real field mock_field = forms.ChoiceField(required=False, # doesn't get submitted choices=[(item, item) for item in _choices], label="The question", widget=forms.Select(attrs={'disabled':'disabled'})) 

Then it is initialized as follows:

 initial_val = 'to be' form = SomeForm(ititial={'field':initial_val, 'mock_field':initial_val}) 

And everything's good. Well, until the form is validated and one of the other fields validates. When this happens, the form reloads and the values ​​are saved, but not one of the "mock_field" - it was never submitted (it was disabled). So it has not survived. Although this does not affect data integrity, it is still not well stated.

Is there a way to save this field with a minimum number of hackers? The form is part of django.contrib.formtools.FormWizard , and the initial values ​​(and some fields) are generated dynamically. In principle, a lot of things are already happening, it would be great if there were no unnecessary things.

+6
python django django-forms
source share
2 answers

Ok, this will be the first time I answer my question, but I found a solution and (so far it is awesome - a hack), it works.

Instead of getting the initial value from the form instance, self.fields['whatever'].initial seems None inside the constructor, I get the value from the keyword argument "initial". And then I set it as the only choice for the "mock" field. Like this:

 from django import forms _choices = ['to be', 'not to be'] class SomeForm(forms.Form): field = forms.ChoiceField(choices=[(item, item) for item in _choices], widget=forms.HiddenInput()) # the real field mock_field = forms.ChoiceField(required=False, # doesn't get submitted choices=[(item, item) for item in _choices], label="The question", widget=forms.Select(attrs={'disabled':'disabled'})) def __init__(self, *args, **kwargs): super(SomeForm, self).__init__(*args, **kwargs) mock_initial = kwargs['initial']['field'] self.fields['mock_field'].choices = [(mock_initial, mock_initial),] 

This probably requires some error handling. Obviously, this will not work if the original value is not specified for the actual field .

+1
source share

Browsers have not disabled POST fields.

You can try to copy the initial field value to mock_field in your __init__ form

 def __init__(self, *args, **kwargs): super(SomeForm, self).__init__(*args, **kwargs) mock_initial = self.fields['field'].initial self.fields['mock_field'].initial = mock_initial 

Code not verified. Usually you are also worried about form.data , but in this case it will not differ from initial

+3
source share

All Articles