from wtforms import Form, StringField, validators from wtforms.fields.choices import SelectMultipleField, RadioField from wtforms.fields.numeric import IntegerField from wtforms.widgets.core import CheckboxInput, ListWidget, Input def validate_therapy_types(form, field): """ Validate form input for given therapy types (mapping in input field) :param form: required by calling method :param field: data field for validation (therapy types) :return: """ # Given choices by the data source valid_choices = {"A", "S", "T", "V"} # All of them in arbitrary sets are allowed if not all(choice in valid_choices for choice in field.data): raise validators.ValidationError("Invalid value in therapy types selection.") def validate_therapy_phone_times(form, field): """ Validate number of weeks for therapy phone times search. :param form: required by calling method :param field: data field for validation (therapy phone times in weeks) :return: """ # Weeks from 1 to 4 valid_choices = {1, 2, 3, 4} # Check for given data at all -> at least 1 week necessary if not field.data: raise validators.ValidationError("Please select at least one option.") # All of them in arbitrary sets are allowed if not all(choice in valid_choices for choice in field.data): raise validators.ValidationError("Invalid value in therapy phone types selection.") class RangeInput(Input): """ Define a range as input type to use HTML element form-range """ input_type = "range" class SearchForm(Form): """ Search Form to search with several parameters and constraints for doctors/therapists with phone times """ # Match location as string or plz with arbitrary length location = StringField("Standort/PLZ", validators=[validators.InputRequired(), validators.Length(min=2, max=50), validators.Regexp("^[a-zA-ZäöüßÄÖÜẞ0-9]+$")]) # Define a distance as range input to limit the search area therapy_distance = IntegerField( "Distanz", widget=RangeInput(), default=25, validators=[validators.InputRequired(), validators.NumberRange(min=0, max=50)] ) # Define several therapy types (all of them possible to search for) therapy_type = SelectMultipleField("Therapieverfahren", choices=[ ("A", "Analytische Psychotherapie"), ("S", "Systemische Therapie"), ("T", "Tiefenpsychologisch fundierte Psychotherapie"), ("V", "Verhaltenstherapie")], option_widget=CheckboxInput(), widget=ListWidget(prefix_label=False), validators=[validate_therapy_types]) # Distinction between adults/children & youth as radio button therapy_age_range = RadioField("Altersgruppe", choices=[ ("E", "Erwachsene"), ("K", "Kinder und Jugendliche")], validators=[validators.InputRequired(), validators.any_of(["E", "K"])]) # Distinction between available therapy types therapy_setting = RadioField("Therapiesetting", choices=[ ("E", "Einzeltherapie"), ("G", "Gruppentherapie")], validators=[validators.InputRequired(), validators.any_of(["E", "G"])]) # TODO: find a better name for label # Choose for how many weeks to show phone times amount_of_weeks = IntegerField( # Rest of the label rendered by the frontend (even though not perfect solution) "Telefonzeiten für die ", widget=RangeInput(), default=1, validators=[validators.InputRequired(), validators.NumberRange(min=1, max=4)] )