improve surverys
This commit is contained in:
+121
-1
@@ -1,3 +1,4 @@
|
||||
import datetime
|
||||
from django import forms
|
||||
from django.forms import ModelMultipleChoiceField
|
||||
from django.contrib.auth.models import User
|
||||
@@ -14,9 +15,30 @@ class SurveyForm(forms.ModelForm):
|
||||
|
||||
class Meta:
|
||||
model = Survey
|
||||
fields = ["name", "description", "active", "anonymous", "authors_only", "author"]
|
||||
fields = [
|
||||
"name",
|
||||
"description",
|
||||
"before_text",
|
||||
"after_text",
|
||||
"active",
|
||||
"anonymous",
|
||||
"authors_only",
|
||||
"author"
|
||||
]
|
||||
widgets = {
|
||||
"description": forms.Textarea(attrs={"rows": 3}),
|
||||
"before_text": forms.Textarea(attrs={"rows": 3, "placeholder": "Instructions shown before the survey starts..."}),
|
||||
"after_text": forms.Textarea(attrs={"rows": 3, "placeholder": "Thank you message shown after submission..."}),
|
||||
}
|
||||
|
||||
|
||||
class SurveyQuestionForm(forms.ModelForm):
|
||||
# Form-only fields for validation rules
|
||||
min_value = forms.IntegerField(required=False, label="Minimum Value (Integer)")
|
||||
max_value = forms.IntegerField(required=False, label="Maximum Value (Integer)")
|
||||
min_date = forms.DateField(required=False, widget=forms.DateInput(attrs={"type": "date"}), label="Minimum Date")
|
||||
max_date = forms.DateField(required=False, widget=forms.DateInput(attrs={"type": "date"}), label="Maximum Date")
|
||||
|
||||
class Meta:
|
||||
model = SurveyQuestion
|
||||
fields = ["text", "question_type", "choices", "required", "position"]
|
||||
@@ -24,6 +46,52 @@ class SurveyQuestionForm(forms.ModelForm):
|
||||
"choices": forms.Textarea(attrs={"rows": 4, "placeholder": "Enter each choice on a new line"}),
|
||||
}
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
# Populate initial values for validation fields from validation_rules dict
|
||||
if self.instance and self.instance.pk and self.instance.validation_rules:
|
||||
rules = self.instance.validation_rules
|
||||
self.fields["min_value"].initial = rules.get("min_value")
|
||||
self.fields["max_value"].initial = rules.get("max_value")
|
||||
|
||||
min_date_val = rules.get("min_date")
|
||||
if min_date_val:
|
||||
try:
|
||||
self.fields["min_date"].initial = datetime.date.fromisoformat(min_date_val)
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
max_date_val = rules.get("max_date")
|
||||
if max_date_val:
|
||||
try:
|
||||
self.fields["max_date"].initial = datetime.date.fromisoformat(max_date_val)
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
def save(self, commit=True):
|
||||
instance = super().save(commit=False)
|
||||
# Build validation_rules dict
|
||||
rules = {}
|
||||
min_val = self.cleaned_data.get("min_value")
|
||||
max_val = self.cleaned_data.get("max_value")
|
||||
min_dt = self.cleaned_data.get("min_date")
|
||||
max_dt = self.cleaned_data.get("max_date")
|
||||
|
||||
if min_val is not None:
|
||||
rules["min_value"] = min_val
|
||||
if max_val is not None:
|
||||
rules["max_value"] = max_val
|
||||
if min_dt is not None:
|
||||
rules["min_date"] = min_dt.isoformat()
|
||||
if max_dt is not None:
|
||||
rules["max_date"] = max_dt.isoformat()
|
||||
|
||||
instance.validation_rules = rules
|
||||
if commit:
|
||||
instance.save()
|
||||
return instance
|
||||
|
||||
|
||||
class SurveyTakeForm(forms.Form):
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.survey = kwargs.pop("survey")
|
||||
@@ -53,6 +121,54 @@ class SurveyTakeForm(forms.Form):
|
||||
choices=[(str(i), str(i)) for i in range(1, 6)],
|
||||
widget=forms.RadioSelect(attrs={"class": "form-check-input"}),
|
||||
)
|
||||
elif q.question_type == SurveyQuestion.QuestionType.INTEGER:
|
||||
rules = q.validation_rules or {}
|
||||
self.fields[field_name] = forms.IntegerField(
|
||||
label=q.text,
|
||||
required=q.required,
|
||||
min_value=rules.get("min_value"),
|
||||
max_value=rules.get("max_value"),
|
||||
widget=forms.NumberInput(attrs={"class": "form-control"})
|
||||
)
|
||||
elif q.question_type == SurveyQuestion.QuestionType.DATE:
|
||||
rules = q.validation_rules or {}
|
||||
attrs = {"type": "date", "class": "form-control"}
|
||||
if rules.get("min_date"):
|
||||
attrs["min"] = rules["min_date"]
|
||||
if rules.get("max_date"):
|
||||
attrs["max"] = rules["max_date"]
|
||||
self.fields[field_name] = forms.DateField(
|
||||
label=q.text,
|
||||
required=q.required,
|
||||
widget=forms.DateInput(attrs=attrs)
|
||||
)
|
||||
|
||||
def clean(self):
|
||||
cleaned_data = super().clean()
|
||||
for q in self.questions:
|
||||
field_name = f"question_{q.pk}"
|
||||
val = cleaned_data.get(field_name)
|
||||
if val is not None and val != "":
|
||||
rules = q.validation_rules or {}
|
||||
if q.question_type == SurveyQuestion.QuestionType.INTEGER:
|
||||
min_val = rules.get("min_value")
|
||||
max_val = rules.get("max_value")
|
||||
if min_val is not None and val < min_val:
|
||||
self.add_error(field_name, f"Value must be at least {min_val}.")
|
||||
if max_val is not None and val > max_val:
|
||||
self.add_error(field_name, f"Value cannot exceed {max_val}.")
|
||||
elif q.question_type == SurveyQuestion.QuestionType.DATE:
|
||||
min_dt_str = rules.get("min_date")
|
||||
max_dt_str = rules.get("max_date")
|
||||
if min_dt_str:
|
||||
min_dt = datetime.date.fromisoformat(min_dt_str)
|
||||
if val < min_dt:
|
||||
self.add_error(field_name, f"Date cannot be before {min_dt_str}.")
|
||||
if max_dt_str:
|
||||
max_dt = datetime.date.fromisoformat(max_dt_str)
|
||||
if val > max_dt:
|
||||
self.add_error(field_name, f"Date cannot be after {max_dt_str}.")
|
||||
return cleaned_data
|
||||
|
||||
def save(self, user=None, cid=None, content_type=None, object_id=None, pre_or_post='GENERAL'):
|
||||
response_user = None if self.survey.anonymous else user
|
||||
@@ -78,5 +194,9 @@ class SurveyTakeForm(forms.Form):
|
||||
ans.choice_answer = val
|
||||
elif q.question_type == SurveyQuestion.QuestionType.RATING:
|
||||
ans.rating_answer = int(val)
|
||||
elif q.question_type == SurveyQuestion.QuestionType.INTEGER:
|
||||
ans.integer_answer = int(val)
|
||||
elif q.question_type == SurveyQuestion.QuestionType.DATE:
|
||||
ans.date_answer = val
|
||||
ans.save()
|
||||
return response
|
||||
|
||||
Reference in New Issue
Block a user