class Meta: model = ProfileUpdateRequest exclude = ('active', 'created_at', 'last_updated_at') widgets = { 'occupation': RadioSelectWithOther('occupation_other'), 'gender': RadioSelectWithOther('gender_other'), 'domains': CheckboxSelectMultipleWithOthers('domains_other'), 'lessons': CheckboxSelectMultipleWithOthers('lessons_other'), 'country': ListSelect2(), }
class Meta: model = EventRequest exclude = ( 'created_at', 'last_updated_at', 'assigned_to', 'data_types', 'data_types_other', 'attendee_data_analysis_level', 'fee_waiver_request', ) widgets = { 'event': Select2Widget, 'approx_attendees': forms.RadioSelect(), 'attendee_domains': CheckboxSelectMultipleWithOthers('attendee_domains_other'), 'attendee_academic_levels': forms.CheckboxSelectMultiple(), 'attendee_computing_levels': forms.CheckboxSelectMultiple(), 'travel_reimbursement': RadioSelectWithOther('travel_reimbursement_other'), 'admin_fee_payment': forms.RadioSelect(), 'country': Select2Widget, }
class Meta: model = TrainingRequest fields = ( 'group_name', 'personal', 'family', 'email', 'github', 'occupation', 'occupation_other', 'affiliation', 'location', 'country', 'underresourced', 'domains', 'domains_other', 'underrepresented', 'nonprofit_teaching_experience', 'previous_involvement', 'previous_training', 'previous_training_other', 'previous_training_explanation', 'previous_experience', 'previous_experience_other', 'previous_experience_explanation', 'programming_language_usage_frequency', 'teaching_frequency_expectation', 'teaching_frequency_expectation_other', 'max_travelling_frequency', 'max_travelling_frequency_other', 'reason', 'user_notes', 'data_privacy_agreement', 'code_of_conduct_agreement', 'training_completion_agreement', 'workshop_teaching_agreement', ) widgets = { 'occupation': RadioSelectWithOther('occupation_other'), 'domains': CheckboxSelectMultipleWithOthers('domains_other'), 'gender': forms.RadioSelect(), 'previous_involvement': forms.CheckboxSelectMultiple(), 'previous_training': RadioSelectWithOther('previous_training_other'), 'previous_experience': RadioSelectWithOther('previous_experience_other'), 'programming_language_usage_frequency': forms.RadioSelect(), 'teaching_frequency_expectation': RadioSelectWithOther('teaching_frequency_expectation_other'), 'max_travelling_frequency': RadioSelectWithOther('max_travelling_frequency_other'), 'country': ListSelect2(), }
class Meta(SWCEventRequestNoCaptchaForm.Meta): exclude = ( 'created_at', 'last_updated_at', 'assigned_to', 'admin_fee_payment', 'attendee_computing_levels', ) widgets = { 'event': Select2(), 'approx_attendees': forms.RadioSelect(), 'attendee_domains': CheckboxSelectMultipleWithOthers('attendee_domains_other'), 'data_types': RadioSelectWithOther('data_types_other'), 'attendee_academic_levels': forms.CheckboxSelectMultiple(), 'attendee_data_analysis_level': forms.CheckboxSelectMultiple(), 'travel_reimbursement': RadioSelectWithOther('travel_reimbursement_other'), }
class WorkshopRequestBaseForm(forms.ModelForm): institution = forms.ModelChoiceField( required=False, queryset=Organization.objects.order_by('fullname'), widget=ListSelect2(), label=WorkshopRequest._meta.get_field('institution').verbose_name, help_text=WorkshopRequest._meta.get_field('institution').help_text, ) domains = forms.ModelMultipleChoiceField( required=False, queryset=KnowledgeDomain.objects.order_by( # this crazy django-ninja-code sorts by 'name', but leaves # "Don't know yet" entry last Case(When(name="Don't know yet", then=-1)), 'name', ), widget=CheckboxSelectMultipleWithOthers('domains_other'), label=WorkshopRequest._meta.get_field('domains').verbose_name, help_text=WorkshopRequest._meta.get_field('domains').help_text, ) travel_expences_agreement = forms.BooleanField( required=True, label=WorkshopRequest._meta.get_field( 'travel_expences_agreement').verbose_name, ) data_privacy_agreement = forms.BooleanField( required=True, label=WorkshopRequest._meta.get_field( 'data_privacy_agreement').verbose_name, ) code_of_conduct_agreement = forms.BooleanField( required=True, label=WorkshopRequest._meta.get_field( 'code_of_conduct_agreement').verbose_name, ) host_responsibilities = forms.BooleanField( required=True, label=WorkshopRequest._meta.get_field( 'host_responsibilities').verbose_name, ) requested_workshop_types = forms.ModelMultipleChoiceField( required=True, queryset=Curriculum.objects.order_by( # This crazy django-ninja-code gives different weights to entries # matching different criterias, and then sorts them by 'name'. # For example when two entries (e.g. swc-r and swc-python) have the # same weight (here: 5), then sorting by name comes in. Case( When(slug="dc-other", then=2), When(slug="lc-other", then=4), When(slug="swc-other", then=6), When(slug="unknown", then=7), When(slug__startswith="dc", then=1), When(slug__startswith="lc", then=3), When(slug__startswith="swc", then=5), default=8, ), 'name', ), label=WorkshopRequest._meta.get_field( 'requested_workshop_types').verbose_name, help_text=WorkshopRequest._meta.get_field( 'requested_workshop_types').help_text, widget=forms.CheckboxSelectMultiple(), ) helper = BootstrapHelper(add_cancel_button=False) class Meta: model = WorkshopRequest fields = ( "personal", "family", "email", "institution", "institution_name", "institution_department", "location", "country", "conference_details", "preferred_dates", "language", "number_attendees", "domains", "domains_other", "academic_levels", "computing_levels", "audience_description", "requested_workshop_types", "organization_type", "self_organized_github", "centrally_organized_fee", "waiver_circumstances", "travel_expences_management", "travel_expences_management_other", "travel_expences_agreement", "user_notes", "data_privacy_agreement", "code_of_conduct_agreement", "host_responsibilities", ) widgets = { 'country': ListSelect2(), 'language': ListSelect2(), 'number_attendees': forms.RadioSelect(), 'academic_levels': forms.CheckboxSelectMultiple(), 'computing_levels': forms.CheckboxSelectMultiple(), 'requested_workshop_types': forms.CheckboxSelectMultiple(), 'organization_type': forms.RadioSelect(), 'centrally_organized_fee': forms.RadioSelect(), 'travel_expences_management': RadioSelectWithOther('travel_expences_management_other'), } def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) # change institution object labels (originally Organization displays # domain as well) self.fields['institution'].label_from_instance = \ self.institution_label_from_instance self.fields['travel_expences_management'].required = False # set up a layout object for the helper self.helper.layout = self.helper.build_default_layout(self) # set up `*WithOther` widgets so that they can display additional # fields inline self['domains'].field.widget.other_field = self['domains_other'] self['travel_expences_management'].field.widget.other_field = \ self['travel_expences_management_other'] # remove additional fields self.helper.layout.fields.remove('domains_other') self.helper.layout.fields.remove('travel_expences_management_other') # get current position of `organization_type` field pos_index = self.helper.layout.fields.index('organization_type') # setup additional information for the field self['organization_type'].field.widget.subfields = { 'self': [ self['self_organized_github'], ], 'central': [ self['centrally_organized_fee'], self['waiver_circumstances'], ], } self['organization_type'].field.widget.notes = { 'self': WorkshopRequest.SELF_ORGANIZED_NOTES, 'central': WorkshopRequest.CENTRALLY_ORGANIZED_NOTES, } self.helper.layout.fields.remove('organization_type') self.helper.layout.fields.remove('self_organized_github') self.helper.layout.fields.remove('centrally_organized_fee') self.helper.layout.fields.remove('waiver_circumstances') # insert div+field at previously saved position self.helper.layout.insert( pos_index, Div( Field('organization_type', template="bootstrap4/layout/radio-accordion.html"), css_class='form-group row', ), ) # add horizontal lines after some fields to visually group them # together hr_fields_after = ( 'email', 'institution_department', 'audience_description', ) hr_fields_before = ( 'travel_expences_management', 'user_notes', ) for field in hr_fields_after: self.helper.layout.insert( self.helper.layout.fields.index(field) + 1, HTML('<hr class="col-lg-10 col-12 mx-0 px-0">'), ) for field in hr_fields_before: self.helper.layout.insert( self.helper.layout.fields.index(field), HTML('<hr class="col-lg-10 col-12 mx-0 px-0">'), ) # move "institution_name" field to "institution" subfield self['institution'].field.widget.subfield = self['institution_name'] self.helper.layout.fields.remove('institution_name') @staticmethod def institution_label_from_instance(obj): """Static method that overrides ModelChoiceField choice labels, essentially works just like `Model.__str__`.""" return "{}".format(obj.fullname) def clean(self): super().clean() errors = dict() # 1: make sure institution is valid institution = self.cleaned_data.get('institution', None) institution_name = self.cleaned_data.get('institution_name', '') if not institution and not institution_name: errors['institution'] = ValidationError('Institution is required.') elif institution and institution_name: errors['institution_name'] = ValidationError( "You must select institution, or enter it's name. " "You can't do both.") # 2: make sure there's institution selected when department is present institution_department = self.cleaned_data \ .get('institution_department', '') if institution_department and not institution and not institution_name: errors['institution_department'] = ValidationError( "You must select institution or enter it's name when you " "enter department/school details.") # 3: * self-organized workshop, require URL # * centrally-organized workshop, require fee description # * fee waiver? require waiver circumstances description organization_type = self.cleaned_data.get('organization_type', '') self_organized_github = self.cleaned_data \ .get('self_organized_github', '') centrally_organized_fee = self.cleaned_data \ .get('centrally_organized_fee', '') waiver_circumstances = self.cleaned_data \ .get('waiver_circumstances', '') if organization_type == 'self' and not self_organized_github: errors['self_organized_github'] = ValidationError( "Please enter workshop URL data.") elif organization_type == 'central' and not centrally_organized_fee: errors['centrally_organized_fee'] = ValidationError( "Please select applicable administrative fee option.") elif organization_type == 'central' and \ centrally_organized_fee == 'waiver' and \ not waiver_circumstances: errors['waiver_circumstances'] = ValidationError( "Please describe your waiver circumstances.") # 5: don't allow empty domains and empty domains_other domains = self.cleaned_data.get('domains', '') domains_other = self.cleaned_data.get('domains_other', '') if not domains and not domains_other: errors['domains'] = ValidationError( "This field is required. If you're uncertain about what to " 'choose, select "Don\'t know yet".') # 6: don't allow empty travel expences management travel_expences_management = \ self.cleaned_data.get('travel_expences_management', '') travel_expences_management_other = \ self.cleaned_data.get('travel_expences_management_other', '') if not travel_expences_management and \ not travel_expences_management_other: errors['travel_expences_management'] = "This field is required." # raise errors if any present if errors: raise ValidationError(errors)
class Meta: model = TrainingRequest fields = ( "review_process", "group_name", "personal", "family", "email", "secondary_email", "github", "occupation", "occupation_other", "affiliation", "location", "country", "underresourced", "domains", "domains_other", "underrepresented", "underrepresented_details", "nonprofit_teaching_experience", "previous_involvement", "previous_training", "previous_training_other", "previous_training_explanation", "previous_experience", "previous_experience_other", "previous_experience_explanation", "programming_language_usage_frequency", "teaching_frequency_expectation", "teaching_frequency_expectation_other", "max_travelling_frequency", "max_travelling_frequency_other", "reason", "user_notes", "data_privacy_agreement", "code_of_conduct_agreement", "training_completion_agreement", "workshop_teaching_agreement", ) widgets = { "review_process": forms.RadioSelect(), "occupation": RadioSelectWithOther("occupation_other"), "domains": CheckboxSelectMultipleWithOthers("domains_other"), "underrepresented": forms.RadioSelect(), "previous_involvement": forms.CheckboxSelectMultiple(), "previous_training": RadioSelectWithOther("previous_training_other"), "previous_experience": RadioSelectWithOther("previous_experience_other"), "programming_language_usage_frequency": forms.RadioSelect(), "teaching_frequency_expectation": RadioSelectWithOther("teaching_frequency_expectation_other"), "max_travelling_frequency": RadioSelectWithOther("max_travelling_frequency_other"), "country": Select2Widget, }