mirror of
https://github.com/pretix/pretix.git
synced 2026-05-07 15:34:02 +00:00
Questions: Validate type changes (Z#23197118) (#5259)
* Questions: Validate type changes (Z#23197118) * Update src/pretix/base/forms/questions.py Co-authored-by: Richard Schreiber <schreiber@rami.io> * Update src/pretix/base/forms/questions.py Co-authored-by: Richard Schreiber <schreiber@rami.io> * Update src/pretix/base/forms/questions.py Co-authored-by: Richard Schreiber <schreiber@rami.io> * Update src/pretix/base/models/items.py Co-authored-by: Richard Schreiber <schreiber@rami.io> * Fix failing test --------- Co-authored-by: Richard Schreiber <schreiber@rami.io>
This commit is contained in:
@@ -896,10 +896,17 @@ class BaseQuestionsForm(forms.Form):
|
||||
'Please enter a date no later than {max}.',
|
||||
max=date_format(q.valid_date_max, "SHORT_DATE_FORMAT"),
|
||||
)
|
||||
if initial and initial.answer:
|
||||
try:
|
||||
_initial = dateutil.parser.parse(initial.answer).date()
|
||||
except dateutil.parser.ParserError:
|
||||
_initial = None
|
||||
else:
|
||||
_initial = None
|
||||
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,
|
||||
initial=_initial,
|
||||
widget=DatePickerWidget(attrs),
|
||||
)
|
||||
if q.valid_date_min:
|
||||
@@ -907,10 +914,17 @@ class BaseQuestionsForm(forms.Form):
|
||||
if q.valid_date_max:
|
||||
field.validators.append(MaxDateValidator(q.valid_date_max))
|
||||
elif q.type == Question.TYPE_TIME:
|
||||
if initial and initial.answer:
|
||||
try:
|
||||
_initial = dateutil.parser.parse(initial.answer).time()
|
||||
except dateutil.parser.ParserError:
|
||||
_initial = None
|
||||
else:
|
||||
_initial = None
|
||||
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,
|
||||
initial=_initial,
|
||||
widget=TimePickerWidget(time_format=get_format_without_seconds('TIME_INPUT_FORMATS')),
|
||||
)
|
||||
elif q.type == Question.TYPE_DATETIME:
|
||||
@@ -931,10 +945,19 @@ class BaseQuestionsForm(forms.Form):
|
||||
'Please enter a date and time no later than {max}.',
|
||||
max=date_format(q.valid_datetime_max, "SHORT_DATETIME_FORMAT"),
|
||||
)
|
||||
|
||||
if initial and initial.answer:
|
||||
try:
|
||||
_initial = dateutil.parser.parse(initial.answer).astimezone(tz)
|
||||
except dateutil.parser.ParserError:
|
||||
_initial = None
|
||||
else:
|
||||
_initial = None
|
||||
|
||||
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,
|
||||
initial=_initial,
|
||||
widget=SplitDateTimePickerWidget(
|
||||
time_format=get_format_without_seconds('TIME_INPUT_FORMATS'),
|
||||
min_date=q.valid_datetime_min,
|
||||
|
||||
@@ -1925,6 +1925,25 @@ class Question(LoggedModel):
|
||||
raise ValidationError(_("The maximum value must not be lower than the minimum value."))
|
||||
super().clean()
|
||||
|
||||
def clean_type_change(self, old_type, new_type):
|
||||
if old_type == new_type:
|
||||
return True
|
||||
if not self.pk or not self.answers.exists():
|
||||
return True
|
||||
if new_type == self.TYPE_TEXT and old_type != self.TYPE_FILE:
|
||||
# All types can be converted to text except file
|
||||
return True
|
||||
if new_type == self.TYPE_STRING and old_type not in (self.TYPE_TEXT, self.TYPE_FILE):
|
||||
# All types can be converted to string except text or file
|
||||
return True
|
||||
if new_type == self.TYPE_CHOICE_MULTIPLE and old_type == self.TYPE_CHOICE:
|
||||
# Single-choice can be converted to multiple choice without loss
|
||||
return True
|
||||
raise ValidationError(
|
||||
_("The system already contains answers to this question that are not compatible with changing the "
|
||||
"type of question without data loss. Consider hiding this question and creating a new one instead.")
|
||||
)
|
||||
|
||||
|
||||
class QuestionOption(models.Model):
|
||||
question = models.ForeignKey('Question', related_name='options', on_delete=models.CASCADE)
|
||||
|
||||
Reference in New Issue
Block a user