def __init__(self, *args, **kwargs): self.event = kwargs.pop('event') self.request = kwargs.pop('request') self.all_optional = kwargs.pop('all_optional', False) super().__init__(*args, **kwargs) if self.event.settings.order_email_asked_twice: self.fields['email_repeat'] = forms.EmailField( label=_('E-mail address (repeated)'), help_text= _('Please enter the same email address again to make sure you typed it correctly.' ), ) if self.event.settings.order_phone_asked: with language(get_babel_locale()): default_country = guess_country(self.event) default_prefix = None for prefix, values in _COUNTRY_CODE_TO_REGION_CODE.items(): if str(default_country) in values: default_prefix = prefix try: initial = self.initial.pop('phone', None) initial = PhoneNumber().from_string( initial) if initial else "+{}.".format(default_prefix) except NumberParseException: initial = None self.fields['phone'] = PhoneNumberField( label=_('Phone number'), required=self.event.settings.order_phone_required, help_text=self.event.settings.checkout_phone_helptext, # We now exploit an implementation detail in PhoneNumberPrefixWidget to allow us to pass just # a country code but no number as an initial value. It's a bit hacky, but should be stable for # the future. initial=initial, widget=WrappedPhoneNumberPrefixWidget()) if not self.request.session.get('iframe_session', False): # There is a browser quirk in Chrome that leads to incorrect initial scrolling in iframes if there # is an autofocus field. Who would have thought… See e.g. here: # https://floatboxjs.com/forum/topic.php?post=8440&usebb_sid=2e116486a9ec6b7070e045aea8cded5b#post8440 self.fields['email'].widget.attrs['autofocus'] = 'autofocus' self.fields[ 'email'].help_text = self.event.settings.checkout_email_helptext responses = contact_form_fields.send(self.event, request=self.request) for r, response in responses: for key, value in response.items(): # We need to be this explicit, since OrderedDict.update does not retain ordering self.fields[key] = value if self.all_optional: for k, v in self.fields.items(): v.required = False v.widget.is_required = False
def __init__(self, initial=None): choices = [("", "---------")] language = get_babel_locale() # changed from default implementation that used the django locale locale = Locale(translation.to_locale(language)) for prefix, values in _COUNTRY_CODE_TO_REGION_CODE.items(): prefix = "+%d" % prefix if initial and initial in values: self.initial = prefix for country_code in values: country_name = locale.territories.get(country_code) if country_name: choices.append((prefix, "{} {}".format(country_name, prefix))) super().__init__(choices=sorted(choices, key=lambda item: item[1]), attrs={'aria-label': pgettext_lazy('phonenumber', 'International area code')})
def __init__(self, *args, **kwargs): self.event = kwargs.pop('event') super().__init__(*args, **kwargs) event = self.event if event.settings.waiting_list_names_asked: self.fields['name_parts'] = NamePartsFormField( max_length=255, required=event.settings.waiting_list_names_required, scheme=event.settings.name_scheme, titles=event.settings.name_scheme_titles, label=_('Name'), ) else: del self.fields['name_parts'] if event.settings.waiting_list_phones_asked: with language(get_babel_locale()): default_country = guess_country(self.event) for prefix, values in _COUNTRY_CODE_TO_REGION_CODE.items(): if str(default_country ) in values and not self.initial.get('phone'): # We now exploit an implementation detail in PhoneNumberPrefixWidget to allow us to pass just # a country code but no number as an initial value. It's a bit hacky, but should be stable for # the future. self.initial['phone'] = "+{}.".format(prefix) self.fields['phone'] = PhoneNumberField( label=_("Phone number"), required=event.settings.waiting_list_phones_required, help_text=event.settings. waiting_list_phones_explanation_text, widget=WrappedPhoneNumberPrefixWidget()) else: del self.fields['phone']
def __init__(self, *args, **kwargs): """ Takes two additional keyword arguments: :param cartpos: The cart position the form should be for :param event: The event this belongs to """ cartpos = self.cartpos = kwargs.pop('cartpos', None) orderpos = self.orderpos = kwargs.pop('orderpos', None) pos = cartpos or orderpos item = pos.item questions = pos.item.questions_to_ask event = kwargs.pop('event') self.all_optional = kwargs.pop('all_optional', False) super().__init__(*args, **kwargs) add_fields = {} if item.admission and event.settings.attendee_names_asked: add_fields['attendee_name_parts'] = NamePartsFormField( max_length=255, required=event.settings.attendee_names_required and not self.all_optional, scheme=event.settings.name_scheme, titles=event.settings.name_scheme_titles, label=_('Attendee name'), initial=(cartpos.attendee_name_parts if cartpos else orderpos.attendee_name_parts), ) if item.admission and event.settings.attendee_emails_asked: add_fields['attendee_email'] = forms.EmailField( required=event.settings.attendee_emails_required and not self.all_optional, label=_('Attendee email'), initial=(cartpos.attendee_email if cartpos else orderpos.attendee_email), widget=forms.EmailInput(attrs={'autocomplete': 'email'})) if item.admission and event.settings.attendee_company_asked: add_fields['company'] = forms.CharField( required=event.settings.attendee_company_required and not self.all_optional, label=_('Company'), max_length=255, initial=(cartpos.company if cartpos else orderpos.company), ) if item.admission and event.settings.attendee_addresses_asked: add_fields['street'] = forms.CharField( required=event.settings.attendee_addresses_required and not self.all_optional, label=_('Address'), widget=forms.Textarea( attrs={ 'rows': 2, 'placeholder': _('Street and Number'), 'autocomplete': 'street-address' }), initial=(cartpos.street if cartpos else orderpos.street), ) add_fields['zipcode'] = forms.CharField( required=event.settings.attendee_addresses_required and not self.all_optional, max_length=30, label=_('ZIP code'), initial=(cartpos.zipcode if cartpos else orderpos.zipcode), widget=forms.TextInput(attrs={ 'autocomplete': 'postal-code', }), ) add_fields['city'] = forms.CharField( required=event.settings.attendee_addresses_required and not self.all_optional, label=_('City'), max_length=255, initial=(cartpos.city if cartpos else orderpos.city), widget=forms.TextInput(attrs={ 'autocomplete': 'address-level2', }), ) country = (cartpos.country if cartpos else orderpos.country) or guess_country(event) add_fields['country'] = CountryField( countries=CachedCountries).formfield( required=event.settings.attendee_addresses_required and not self.all_optional, label=_('Country'), initial=country, widget=forms.Select(attrs={ 'autocomplete': 'country', }), ) c = [('', pgettext_lazy('address', 'Select state'))] fprefix = str( self.prefix ) + '-' if self.prefix is not None and self.prefix != '-' else '' cc = None if fprefix + 'country' in self.data: cc = str(self.data[fprefix + 'country']) elif country: cc = str(country) if cc and cc in COUNTRIES_WITH_STATE_IN_ADDRESS: types, form = COUNTRIES_WITH_STATE_IN_ADDRESS[cc] statelist = [ s for s in pycountry.subdivisions.get(country_code=cc) if s.type in types ] c += sorted([(s.code[3:], s.name) for s in statelist], key=lambda s: s[1]) elif fprefix + 'state' in self.data: self.data = self.data.copy() del self.data[fprefix + 'state'] add_fields['state'] = forms.ChoiceField( label=pgettext_lazy('address', 'State'), required=False, choices=c, widget=forms.Select(attrs={ 'autocomplete': 'address-level1', }), ) add_fields['state'].widget.is_required = True field_positions = list([(n, event.settings.system_question_order.get( n if n != 'state' else 'country', 0)) for n in add_fields.keys()]) for q in questions: # Do we already have an answer? Provide it as the initial value answers = [a for a in pos.answerlist if a.question_id == q.id] if answers: initial = answers[0] else: initial = None tz = pytz.timezone(event.settings.timezone) help_text = rich_text(q.help_text) label = escape(q.question) # django-bootstrap3 calls mark_safe required = q.required and not self.all_optional if q.type == Question.TYPE_BOOLEAN: if q.required: # For some reason, django-bootstrap3 does not set the required attribute # itself. widget = forms.CheckboxInput( attrs={'required': 'required'}) else: widget = forms.CheckboxInput() if initial: initialbool = (initial.answer == "True") else: initialbool = False field = forms.BooleanField( label=label, required=required, help_text=help_text, initial=initialbool, widget=widget, ) elif q.type == Question.TYPE_NUMBER: field = forms.DecimalField( label=label, required=required, min_value=q.valid_number_min or Decimal('0.00'), max_value=q.valid_number_max, help_text=q.help_text, initial=initial.answer if initial else None, ) elif q.type == Question.TYPE_STRING: field = forms.CharField( label=label, required=required, help_text=help_text, initial=initial.answer if initial else None, ) elif q.type == Question.TYPE_TEXT: field = forms.CharField( label=label, required=required, help_text=help_text, widget=forms.Textarea, initial=initial.answer if initial else None, ) elif q.type == Question.TYPE_COUNTRYCODE: field = CountryField( countries=CachedCountries, blank=True, null=True, blank_label=' ', ).formfield( label=label, required=required, help_text=help_text, widget=forms.Select, empty_label=' ', initial=initial.answer if initial else (guess_country(event) if required else None), ) elif q.type == Question.TYPE_CHOICE: field = forms.ModelChoiceField( queryset=q.options, label=label, required=required, help_text=help_text, widget=forms.Select, to_field_name='identifier', empty_label='', initial=initial.options.first() if initial else None, ) elif q.type == Question.TYPE_CHOICE_MULTIPLE: field = forms.ModelMultipleChoiceField( queryset=q.options, label=label, required=required, help_text=help_text, to_field_name='identifier', widget=QuestionCheckboxSelectMultiple, initial=initial.options.all() if initial else None, ) elif q.type == Question.TYPE_FILE: field = ExtFileField( label=label, required=required, help_text=help_text, initial=initial.file if initial else None, widget=UploadedFileWidget(position=pos, event=event, answer=initial), ext_whitelist=(".png", ".jpg", ".gif", ".jpeg", ".pdf", ".txt", ".docx", ".gif", ".svg", ".pptx", ".ppt", ".doc", ".xlsx", ".xls", ".jfif", ".heic", ".heif", ".pages", ".bmp", ".tif", ".tiff"), max_size=10 * 1024 * 1024, ) elif q.type == Question.TYPE_DATE: attrs = {} if q.valid_date_min: attrs['data-min'] = q.valid_date_min.isoformat() if q.valid_date_max: attrs['data-max'] = q.valid_date_max.isoformat() field = forms.DateField( label=label, required=required, help_text=help_text, initial=dateutil.parser.parse(initial.answer).date() if initial and initial.answer else None, widget=DatePickerWidget(attrs), ) if q.valid_date_min: field.validators.append(MinDateValidator(q.valid_date_min)) if q.valid_date_max: field.validators.append(MaxDateValidator(q.valid_date_max)) elif q.type == Question.TYPE_TIME: field = forms.TimeField( label=label, required=required, help_text=help_text, initial=dateutil.parser.parse(initial.answer).time() if initial and initial.answer else None, widget=TimePickerWidget( time_format=get_format_without_seconds( 'TIME_INPUT_FORMATS')), ) elif q.type == Question.TYPE_DATETIME: field = SplitDateTimeField( label=label, required=required, help_text=help_text, initial=dateutil.parser.parse( initial.answer).astimezone(tz) if initial and initial.answer else None, widget=SplitDateTimePickerWidget( time_format=get_format_without_seconds( 'TIME_INPUT_FORMATS'), min_date=q.valid_datetime_min, max_date=q.valid_datetime_max), ) if q.valid_datetime_min: field.validators.append( MinDateTimeValidator(q.valid_datetime_min)) if q.valid_datetime_max: field.validators.append( MaxDateTimeValidator(q.valid_datetime_max)) elif q.type == Question.TYPE_PHONENUMBER: with language(get_babel_locale()): default_country = guess_country(event) default_prefix = None for prefix, values in _COUNTRY_CODE_TO_REGION_CODE.items(): if str(default_country) in values: default_prefix = prefix try: initial = PhoneNumber().from_string( initial.answer) if initial else "+{}.".format( default_prefix) except NumberParseException: initial = None field = PhoneNumberField( label=label, required=required, help_text=help_text, # We now exploit an implementation detail in PhoneNumberPrefixWidget to allow us to pass just # a country code but no number as an initial value. It's a bit hacky, but should be stable for # the future. initial=initial, widget=WrappedPhoneNumberPrefixWidget()) field.question = q if answers: # Cache the answer object for later use field.answer = answers[0] if q.dependency_question_id: field.widget.attrs[ 'data-question-dependency'] = q.dependency_question_id field.widget.attrs[ 'data-question-dependency-values'] = escapejson_attr( json.dumps(q.dependency_values)) if q.type != 'M': field.widget.attrs[ 'required'] = q.required and not self.all_optional field._required = q.required and not self.all_optional field.required = False add_fields['question_%s' % q.id] = field field_positions.append(('question_%s' % q.id, q.position)) field_positions.sort(key=lambda e: e[1]) for fname, p in field_positions: self.fields[fname] = add_fields[fname] responses = question_form_fields.send(sender=event, position=pos) data = pos.meta_info_data for r, response in sorted(responses, key=lambda r: str(r[0])): for key, value in response.items(): # We need to be this explicit, since OrderedDict.update does not retain ordering self.fields[key] = value value.initial = data.get('question_form_data', {}).get(key) for k, v in self.fields.items(): if v.widget.attrs.get( 'autocomplete') or k == 'attendee_name_parts': v.widget.attrs['autocomplete'] = 'section-{} '.format( self.prefix) + v.widget.attrs.get('autocomplete', '')
def guess_phone_prefix(event): with language(get_babel_locale()): country = str(guess_country(event)) return get_phone_prefix(country)
def __init__(self, *args, **kwargs): with language(get_babel_locale()): super().__init__(*args, **kwargs)
def __init__(self, *args, **kwargs): self.event = kwargs.pop('event') self.channel = kwargs.pop('channel') super().__init__(*args, **kwargs) choices = [('', '')] items, display_add_to_cart = get_grouped_items(self.event, self.instance.subevent, require_seat=None) for i in items: if not i.allow_waitinglist: continue if i.has_variations: for v in i.available_variations: if v.cached_availability[0] == Quota.AVAILABILITY_OK: continue choices.append((f'{i.pk}-{v.pk}', f'{i.name} – {v.value}')) else: if i.cached_availability[0] == Quota.AVAILABILITY_OK: continue choices.append((f'{i.pk}', f'{i.name}')) self.fields['itemvar'] = forms.ChoiceField( label=_('Product'), choices=choices, ) event = self.event if event.settings.waiting_list_names_asked: self.fields['name_parts'] = NamePartsFormField( max_length=255, required=event.settings.waiting_list_names_required, scheme=event.settings.name_scheme, titles=event.settings.name_scheme_titles, label=_('Name'), ) else: del self.fields['name_parts'] if event.settings.waiting_list_phones_asked: with language(get_babel_locale()): default_country = guess_country(self.event) for prefix, values in _COUNTRY_CODE_TO_REGION_CODE.items(): if str(default_country ) in values and not self.initial.get('phone'): # We now exploit an implementation detail in PhoneNumberPrefixWidget to allow us to pass just # a country code but no number as an initial value. It's a bit hacky, but should be stable for # the future. self.initial['phone'] = "+{}.".format(prefix) self.fields['phone'] = PhoneNumberField( label=_("Phone number"), required=event.settings.waiting_list_phones_required, help_text=event.settings. waiting_list_phones_explanation_text, widget=WrappedPhoneNumberPrefixWidget()) else: del self.fields['phone']