Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django modelform remove "required" attribute based on other field choice

I have ModelForm with several fields. Some of fields are required, some not. Also I have Select field with different choices, and I want to make some of fields "required" or not based on this Select field choice.

I tried in clean() method of Form

def clean(self):
    cleaned_data = self.cleaned_data
    some_field = cleaned_data.get("some_field")
    if some_field == 'some_value':
          self.fields['other_field'].required = False
    return cleaned_data

but it doesn't work

like image 569
Igor Avatar asked Aug 17 '11 12:08

Igor


People also ask

How do you exclude a specific field from a ModelForm?

Set the exclude attribute of the ModelForm 's inner Meta class to a list of fields to be excluded from the form.

How do you remove this field is required Django?

If yes try to disable this behavior, set the novalidate attribute on the form tag As <form action="{% url 'new_page' %}", method="POST" novalidate> in your html file.

How do you make a field optional in Django?

In order to make a field optional, we have to say so explicitly. If we want to make the pub_time field optional, we add blank=True to the model, which tells Django's field validation that pub_time can be empty.

What is clean method in Django?

The clean_<fieldname>() method is called on a form subclass – where <fieldname> is replaced with the name of the form field attribute. This method does any cleaning that is specific to that particular attribute, unrelated to the type of field that it is. This method is not passed any parameters.


2 Answers

See the Django documentation on Cleaning and validating fields that depend on each other. The standard practice would be to perform the following handling instead:

def clean(self):
    cleaned_data = self.cleaned_data
    some_field = cleaned_data.get("some_field")
    if some_field == 'some_value':
          # 'other_field' is conditionally required.
          if not cleaned_data['other_field']:
              raise forms.ValidationError("'Other_field' is required.")
    return cleaned_data
like image 102
André Caron Avatar answered Sep 25 '22 20:09

André Caron


You have the right idea but the problem is that the individual field validations have already run before the form clean. You have a couple options. You could make the field not required and handle the logic of when it is required in your form.clean. Or you could leave the field as required and remove the validation errors it might raise in the clean.

def clean(self):
    cleaned_data = self.cleaned_data
    some_field = cleaned_data.get("some_field")
    if some_field == 'some_value':
          if 'other_field' in self.errors:
              del self.errors['other_field']
              cleaned_data['other_field'] = None
    return cleaned_data

This has some problems in that it removes all errors, not just missing/required errors. There is also a problem with the cleaned_data. You now have a required field which isn't in the cleaned_data which is why I've added it as None. The rest of your application will have to handle this case. It might seem odd to have a required field which doesn't have a value.

like image 31
Mark Lavin Avatar answered Sep 21 '22 20:09

Mark Lavin