class RegisterForm(forms.ModelForm): dob = forms.DateField( required=True, label='Date of Birth', widget=DatePickerWidget(), ) dob_again = forms.DateField( required=True, label='Date of Birth again', widget=DatePickerWidget(), ) email = forms.CharField( widget=forms.TextInput(attrs={'class': 'form-control'}), label="E-mail address") email_again = forms.CharField( widget=forms.TextInput(attrs={'class': 'form-control'}), label="E-mail address again") first_name = forms.CharField( widget=forms.TextInput(attrs={'class': 'form-control'}), label="Legal First Name") last_name = forms.CharField( widget=forms.TextInput(attrs={'class': 'form-control'}), label="Legal Last Name") class Meta: model = LotteryEntry fields = ["email", "email_again", "first_name", "last_name", "dob"]
class BankTransactionFilterForm(forms.Form): search_text = forms.CharField(required=False, widget=forms.TextInput(attrs={'class': "form-control", "placeholder": _("Search text")})) amount_min = forms.DecimalField(required=False, localize=True, widget=forms.TextInput(attrs={'class': "form-control", "placeholder": _("min"), "size": 8})) amount_max = forms.DecimalField(required=False, localize=True, widget=forms.TextInput(attrs={'class': "form-control", "placeholder": _("max"), "size": 8})) date_min = forms.DateField(required=False, widget=DatePickerWidget(attrs={"size": 8})) date_max = forms.DateField(required=False, widget=DatePickerWidget(attrs={"size": 8})) def is_valid(self): return super().is_valid() and any(value for value in self.cleaned_data.values()) def filter(self, qs): if not self.is_valid(): raise ValueError(_("Filter form is not valid.")) if self.cleaned_data.get('search_text'): q = self.cleaned_data['search_text'] qs = qs.filter(Q(payer__icontains=q) | Q(reference__icontains=q) | Q(comment__icontains=q) | Q(iban__icontains=q) | Q(bic__icontains=q)) if self.cleaned_data.get('amount_min') is not None: qs = qs.filter(amount__gte=self.cleaned_data['amount_min']) if self.cleaned_data.get("amount_max") is not None: qs = qs.filter(amount__lte=self.cleaned_data['amount_max']) if self.cleaned_data.get('date_min') is not None: qs = qs.filter(date_parsed__gte=self.cleaned_data['date_min']) if self.cleaned_data.get('date_max') is not None: qs = qs.filter(date_parsed__lte=self.cleaned_data['date_max']) return qs
class Meta: model = Question localized_fields = '__all__' fields = [ 'question', 'help_text', 'type', 'required', 'ask_during_checkin', 'hidden', 'identifier', 'items', 'dependency_question', 'dependency_values', 'print_on_invoice', 'valid_number_min', 'valid_number_max', 'valid_datetime_min', 'valid_datetime_max', 'valid_date_min', 'valid_date_max', 'valid_file_portrait', ] widgets = { 'valid_datetime_min': SplitDateTimePickerWidget(), 'valid_datetime_max': SplitDateTimePickerWidget(), 'valid_date_min': DatePickerWidget(), 'valid_date_max': DatePickerWidget(), 'items': forms.CheckboxSelectMultiple( attrs={'class': 'scrolling-multiple-choice'}), 'dependency_values': forms.SelectMultiple, } field_classes = { 'valid_datetime_min': SplitDateTimeField, 'valid_datetime_max': SplitDateTimeField, 'items': ItemMultipleChoiceField, 'dependency_question': SafeModelChoiceField, }
class Meta: model = Order fields = ['comment', 'checkin_attention', 'custom_followup_at'] widgets = { 'comment': forms.Textarea(attrs={ 'rows': 3, 'class': 'helper-width-100', }), 'custom_followup_at': DatePickerWidget(), }
class MarkPaidForm(ConfirmPaymentForm): amount = forms.DecimalField( required=True, max_digits=10, decimal_places=2, localize=True, label=_('Payment amount'), ) payment_date = forms.DateField( required=True, label=_('Payment date'), widget=DatePickerWidget(), initial=now ) def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) change_decimal_field(self.fields['amount'], self.instance.event.currency) self.fields['amount'].initial = max(Decimal('0.00'), self.instance.pending_sum)
def __init__(self, *args, **kwargs): self.mixed_values = kwargs.pop('mixed_values') self.queryset = kwargs.pop('queryset') super().__init__(*args, **kwargs) self.fields['location'].widget.attrs['rows'] = '3' for k in ('name', 'location', 'frontpage_text'): # i18n fields if k in self.mixed_values: self.fields[k].widget.attrs['placeholder'] = '[{}]'.format( _('Selection contains various values')) else: self.fields[k].widget.attrs['placeholder'] = '' self.fields[k].one_required = False for k in ('geo_lat', 'geo_lon'): # scalar fields if k in self.mixed_values: self.fields[k].widget.attrs['placeholder'] = '[{}]'.format( _('Selection contains various values')) else: self.fields[k].widget.attrs['placeholder'] = '' self.fields[k].widget.is_required = False self.fields[k].required = False for k in ('date_from', 'date_to', 'date_admission', 'presale_start', 'presale_end'): self.fields[k + '_day'] = forms.DateField( label=self._meta.model._meta.get_field(k).verbose_name, help_text=self._meta.model._meta.get_field(k).help_text, widget=DatePickerWidget(), required=False, ) self.fields[k + '_time'] = forms.TimeField( label=self._meta.model._meta.get_field(k).verbose_name, help_text=self._meta.model._meta.get_field(k).help_text, widget=TimePickerWidget(), required=False, )
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: babel_locale = 'en' # Babel, and therefore django-phonenumberfield, do not support our custom locales such das de_Informal if localedata.exists(get_language()): babel_locale = get_language() elif localedata.exists(get_language()[:2]): babel_locale = get_language()[:2] with language(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 __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) if item.admission and event.settings.attendee_names_asked: self.fields['attendee_name_parts'] = NamePartsFormField( max_length=255, required=event.settings.attendee_names_required, 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: self.fields['attendee_email'] = forms.EmailField( required=event.settings.attendee_emails_required, label=_('Attendee email'), initial=(cartpos.attendee_email if cartpos else orderpos.attendee_email), widget=forms.EmailInput(attrs={'autocomplete': 'email'})) 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, help_text=q.help_text, initial=initial.answer if initial else None, min_value=Decimal('0.00'), ) 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().formfield( label=label, required=required, help_text=help_text, widget=forms.Select, empty_label='', initial=initial.answer if initial 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=forms.CheckboxSelectMultiple, initial=initial.options.all() if initial else None, ) elif q.type == Question.TYPE_FILE: field = forms.FileField( label=label, required=required, help_text=help_text, initial=initial.file if initial else None, widget=UploadedFileWidget(position=pos, event=event, answer=initial), ) elif q.type == Question.TYPE_DATE: 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(), ) 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')), ) elif q.type == Question.TYPE_PHONENUMBER: babel_locale = 'en' # Babel, and therefore django-phonenumberfield, do not support our custom locales such das de_Informal if localedata.exists(get_language()): babel_locale = get_language() elif localedata.exists(get_language()[:2]): babel_locale = get_language()[:2] with language(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 self.fields['question_%s' % q.id] = field 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 __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.fields['date'].widget = DatePickerWidget()
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) if item.admission and event.settings.attendee_names_asked: self.fields['attendee_name_parts'] = NamePartsFormField( max_length=255, required=event.settings.attendee_names_required, scheme=event.settings.name_scheme, label=_('Attendee name'), initial=(cartpos.attendee_name_parts if cartpos else orderpos.attendee_name_parts), ) if item.admission and event.settings.attendee_emails_asked: self.fields['attendee_email'] = forms.EmailField( required=event.settings.attendee_emails_required, label=_('Attendee email'), initial=(cartpos.attendee_email if cartpos else orderpos.attendee_email)) 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, help_text=q.help_text, initial=initial.answer if initial else None, min_value=Decimal('0.00'), ) 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_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=forms.CheckboxSelectMultiple, initial=initial.options.all() if initial else None, ) elif q.type == Question.TYPE_FILE: field = forms.FileField( label=label, required=required, help_text=help_text, initial=initial.file if initial else None, widget=UploadedFileWidget(position=pos, event=event, answer=initial), ) elif q.type == Question.TYPE_DATE: 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(), ) 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')), ) 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-value'] = q.dependency_value 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 self.fields['question_%s' % q.id] = field 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)
class StretchgoalsSettingsForm(I18nForm, SettingsForm): # General settings stretchgoals_start_date = forms.DateField( required=False, label=_('Start date'), widget=DatePickerWidget(), help_text=_('Will start at first sale by default.'), ) stretchgoals_end_date = forms.DateField( required=False, label=_('End date'), widget=DatePickerWidget(), help_text=_('Will end at last sale by default.'), ) stretchgoals_items = SafeModelMultipleChoiceField( queryset=Item.objects.none(), required=False, label=_('Item types'), help_text=_('Items to be included in the calculation.'), widget=forms.CheckboxSelectMultiple, ) stretchgoals_include_pending = forms.BooleanField( required=False, label=_('Include pending orders'), help_text=_( 'By default, only paid orders are included in the calculation.'), ) # Goal settings stretchgoals_new_name = I18nFormField(required=False, label=_('New goal\'s name'), widget=I18nTextInput) stretchgoals_new_total = forms.IntegerField( required=False, min_value=0, label=_('New total revenue goal')) stretchgoals_new_amount = forms.IntegerField( required=False, min_value=0, label=_('New goal\'s amount of items to be sold')) stretchgoals_new_description = I18nFormField( required=False, label=_('New goal\'s description'), widget=I18nTextarea) # Display settings stretchgoals_is_public = forms.BooleanField( required=False, label=_('Show publicly'), help_text=_('By default, the chart is only shown in the backend.'), ) stretchgoals_calculation_text = forms.BooleanField( required=False, label=_('Show public text'), help_text= _('This text will include the current state and extrapolations for all goals.' ), ) stretchgoals_chart_averages = forms.BooleanField( required=False, label=_('Generate average price graph'), help_text=_( 'This graph shows the development of the average price paid.'), ) stretchgoals_chart_totals = forms.BooleanField( required=False, label=_('Generate total revenue graph'), help_text=_('This graph shows the total revenue over time.'), ) stretchgoals_chart_itemsales = forms.BooleanField( required=False, label=_('Generate sold items graph'), help_text=_( 'This graph shows the total amount of sold items over time.'), ) stretchgoals_show_itemsales_items = forms.BooleanField( required=False, label=_('Show individual products in sold items graph'), help_text=_( 'If this option is disabled, an aggregated number will only be shown in the sold items graph.' 'Else, a per-item breakdown will be displayed'), widget=forms.CheckboxInput( attrs={ 'data-checkbox-dependency': '#id_stretchgoals_chart_itemsales' }), ) stretchgoals_min_orders = forms.IntegerField( required=False, label=_('Minimal number of orders'), help_text= _('Only show the graph if more than this many orders are taken into consideration.' ), ) stretchgoals_public_text = I18nFormField( required=False, label=_('Text shown on the public page'), help_text=_( 'Text shown on the public page. You can use the placeholder ' '{avg_now} (the current average).'), widget=I18nTextarea, ) def __init__(self, *args, **kwargs): """ Reduce possible friends_ticket_items to items of this event. """ self.event = kwargs.pop('event') super().__init__(*args, **kwargs) initial_items = (self.event.settings.get('stretchgoals_items', as_type=QuerySet) or []) if isinstance(initial_items, str) and initial_items: initial_items = self.event.items.filter( id__in=initial_items.split(',')) elif isinstance(initial_items, list): initial_items = self.event.items.filter( id__in=[i.pk for i in initial_items]) self.fields['stretchgoals_items'].queryset = Item.objects.filter( event=self.event) self.initial['stretchgoals_items'] = initial_items self.goals = get_goals(self.event) def _save_new_goal(self): goals = json.loads( self.event.settings.get('stretchgoals_goals') or "[]") new_goal = dict() for item in ['name', 'total', 'amount', 'description']: new_goal[item] = self.cleaned_data.pop( 'stretchgoals_new_{}'.format(item)) self.fields.pop('stretchgoals_new_{}'.format(item)) if new_goal['total']: goals.append(new_goal) set_goals(self.event, goals) def save(self, *args, **kwargs): self._save_new_goal() self.event.settings._h.add_type( QuerySet, lambda queryset: ','.join( [str(element.pk) for element in queryset]), lambda pk_list: Item.objects.filter(pk__in=list( filter(None, pk_list.split(','))))) super().save(*args, **kwargs)
def get_content_field(self, q, initial): tz = pytz.timezone(self.placeholder.question.event.settings.timezone) label = "" help_text = "" required = False if q.type == Question.TYPE_BOOLEAN: widget = forms.CheckboxInput() initialbool = initial == "True" return forms.BooleanField( label=label, required=False, help_text=help_text, initial=initialbool, widget=widget, ) if q.type == Question.TYPE_NUMBER: return forms.DecimalField( label=label, required=required, help_text=q.help_text, initial=initial, ) if q.type == Question.TYPE_STRING: return forms.CharField( label=label, required=required, help_text=help_text, initial=initial, ) if q.type == Question.TYPE_TEXT: return forms.CharField( label=label, required=required, help_text=help_text, widget=forms.Textarea, initial=initial, ) if q.type == Question.TYPE_COUNTRYCODE: return 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, ) if q.type == Question.TYPE_CHOICE: return forms.ModelChoiceField( queryset=q.options, label=label, required=required, help_text=help_text, widget=forms.Select, to_field_name="identifier", empty_label="", initial=q.options.filter( pk=initial).first() if initial else None, ) elif q.type == Question.TYPE_CHOICE_MULTIPLE: return forms.ModelMultipleChoiceField( queryset=q.options, label=label, required=required, help_text=help_text, to_field_name="identifier", widget=QuestionCheckboxSelectMultiple, initial=initial, ) 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).date() if initial and initial 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)) return field elif q.type == Question.TYPE_TIME: return forms.TimeField( label=label, required=required, help_text=help_text, initial=dateutil.parser.parse(initial).time() if initial and initial 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).astimezone(tz) if initial 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)) return field elif q.type == Question.TYPE_PHONENUMBER: return PhoneNumberField( label=label, required=required, help_text=help_text, initial=initial, widget=WrappedPhoneNumberPrefixWidget(), )