I have a form with two fields. The user should be required to only select one of the two. Not both and not none. I tried solving this by overwriting the clean method as described in the Django Doc:
forms.py
class ConfigureWorkout(forms.Form):
first_exercise = forms.ModelChoiceField(empty_label="select", label="Choose First Exercise", queryset=FirstExercise.objects.all(), required=False)
sec_exercise = forms.ModelChoiceField(empty_label="select", label="Choose Sec Exercise", queryset=SecExercise.objects.all(), required=False)
def clean(self):
first_exercise = self.cleaned_data.get("first_exercise")
sec_exercise = self.cleaned_data.get("sec_exercise")
if first_exercise and sec_exercise:
raise forms.ValidationError("Enter either a First Exercise or a Secondary Exercise.")
else:
return self.cleaned_data
views.py
def configure(request):
configure_workout = ConfigureWorkout()
if request.method == "GET":
return render(request, "userprofile/some.html", configure_workout)
else:
return render(request, "app/other.html")
template
<form action="{% url 'configure' %}" method="POST">
{% csrf_token %}
{{ configure_workout }}
<input type="submit" name="configuration_completed">
</form>
However, if I test this by selecting both fields in the form, there won't be an error displayed/raised. I pass the form successfully and get sent to "other.html".
What am I missing? Thanks so much in advance for any help :)
CodePudding user response:
It seems you're not passing actual data to your form. Maybe this will help:
def configure(request):
configure_workout = ConfigureWorkout()
if request.method == "GET":
return render(request, "userprofile/some.html", configure_workout)
else:
configure_workout = ConfigureWorkout(request.POST)
configure_workout.is_valid()
configure_workout.clean()
return render(request, "app/other.html")
CodePudding user response:
Building on @trafalinos answer and looking at the documentation on Forms, I would suggest doing the following:
In forms.py
:
class ConfigureWorkout(forms.Form):
first_exercise = forms.ModelChoiceField(empty_label="select", label="Choose First Exercise", queryset=FirstExercise.objects.all(), required=False)
sec_exercise = forms.ModelChoiceField(empty_label="select", label="Choose Sec Exercise", queryset=SecExercise.objects.all(), required=False)
def clean(self):
cleaned_data = super().clean() # compare documentation
first_exercise = cleaned_data.get("first_exercise")
sec_exercise = cleaned_data.get("sec_exercise")
if first_exercise and sec_exercise:
raise forms.ValidationError("Enter either a First Exercise or a Secondary Exercise.")
else:
return self.cleaned_data
And (credits to trafalino) in views.py
:
def configure(request):
if request.method == "GET":
configure_workout = ConfigureWorkout()
return render(request, "userprofile/some.html", configure_workout)
else:
configure_workout = ConfigureWorkout(request.POST)
configure_workout.clean()
return render(request, "app/other.html")