Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django form validation: making "required" conditional?

I'm new to Django (and Python), and am trying to figure out how to conditionalize certain aspects of form validation. In this case, there's a HTML interface to the application where the user can choose a date and a time from widgets. The clean method on the form object takes the values of the time and date fields and turns them back into a datetime.

In addition to the HTML interface, there's also an iPhone client making calls into the application, and I'd like to pass a UNIX timestamp-style time value in.

My form code looks like this:

class FooForm(forms.ModelForm):
    foo_date             = forms.CharField(required=True, widget=forms.RadioSelect(choices=DATE_CHOICES))
    foo_time             = forms.CharField(required=True, widget=SelectTimeWidget())
    foo_timestamp        = forms.CharField(required=False)

How do I make foo_date and foo_time required unless foo_timestamp is provided?

like image 285
Chris W. Avatar asked Feb 21 '10 18:02

Chris W.


People also ask

How do you make a field required in Django?

Let's try to use required via Django Web application we created, visit http://localhost:8000/ and try to input the value based on option or validation applied on the Field. Hit submit. Hence Field is accepting the form even without any data in the geeks_field. This makes required=False implemented successfully.

How does Django validate form data?

Django provides built-in methods to validate form data automatically. Django forms submit only if it contains CSRF tokens. It uses uses a clean and easy approach to validate data. The is_valid() method is used to perform validation for each field of the form, it is defined in Django Form class.

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.

What is clean method in Django?

The clean() method on a Field subclass is responsible for running to_python() , validate() , and run_validators() in the correct order and propagating their errors. If, at any time, any of the methods raise ValidationError , the validation stops and that error is raised.


2 Answers

This is done with the clean method on the form. You need to set foo_date and foo_time to required=False, though, because clean is only called after every field has been validated (see also the documentation).

class FooForm(forms.Form)
    # your field definitions

    def clean(self):
        data = self.cleaned_data
        if data.get('foo_timestamp', None) or (data.get('foo_date', None) and data.get('foo_time', None)):
            return data
        else:
            raise forms.ValidationError('Provide either a date and time or a timestamp')
like image 61
Benjamin Wohlwend Avatar answered Oct 01 '22 12:10

Benjamin Wohlwend


I found myself needing a "standard" way to do this, as my forms have several conditionally required fields. So I created a superclass with the following method:

def validate_required_field(self, cleaned_data, field_name, message="This field is required"):
    if(field_name in cleaned_data and cleaned_data[field_name] is None):
        self._errors[field_name] = self.error_class([message])
        del cleaned_data[field_name]

And then in my form's clean method I have:

def clean(self):
    cleaned_data = super(FormClass, self).clean()
    if(condition):
        self.validate_required_field(cleaned_data, 'field_name')

It's worked perfectly for me so far.

like image 22
Elliott Avatar answered Oct 01 '22 14:10

Elliott