Skip to content

Commit

Permalink
feat: add dynamic form generation
Browse files Browse the repository at this point in the history
  • Loading branch information
twinkarma committed Dec 3, 2024
1 parent e7504f5 commit dc53e6d
Show file tree
Hide file tree
Showing 36 changed files with 396 additions and 611 deletions.
1 change: 0 additions & 1 deletion SORT/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@

"home",
"survey",
"invites",
]

MIDDLEWARE = [
Expand Down
1 change: 0 additions & 1 deletion home/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
path('logout/', views.LogoutInterfaceView.as_view(), name='logout'),
path('signup/', views.SignupView.as_view(), name='signup'),
path('', include('survey.urls'), name='survey'),
path('invite/', include('invites.urls'), name='invites'),
path('profile/', views.ProfileView.as_view(), name='profile'),
path('password_reset/', views.CustomPasswordResetView.as_view(), name='password_reset'),
path('password_reset/done/', views.CustomPasswordResetDoneView.as_view(), name='password_reset_done'),
Expand Down
4 changes: 2 additions & 2 deletions home/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from django.contrib.auth.views import LoginView, LogoutView
from django.views.generic.edit import CreateView, UpdateView
from django.shortcuts import redirect
from survey.models import Questionnaire
from survey.models import Survey
from django.shortcuts import render
from django.views import View
from .forms import ManagerSignupForm, ManagerLoginForm, UserProfileForm
Expand Down Expand Up @@ -44,7 +44,7 @@ class HomeView(LoginRequiredMixin, View):
template_name = 'home/welcome.html'
login_url = 'login'
def get(self, request):
consent_questionnaire = Questionnaire.objects.get(
consent_questionnaire = Survey.objects.get(
title="Consent")
return render(request, 'home/welcome.html', {'questionnaire': consent_questionnaire})

Expand Down
Empty file removed invites/__init__.py
Empty file.
3 changes: 0 additions & 3 deletions invites/admin.py

This file was deleted.

6 changes: 0 additions & 6 deletions invites/apps.py

This file was deleted.

9 changes: 0 additions & 9 deletions invites/forms.py

This file was deleted.

39 changes: 0 additions & 39 deletions invites/migrations/0001_initial.py

This file was deleted.

19 changes: 0 additions & 19 deletions invites/migrations/0002_alter_invitation_token.py

This file was deleted.

Empty file removed invites/migrations/__init__.py
Empty file.
22 changes: 0 additions & 22 deletions invites/models.py

This file was deleted.

3 changes: 0 additions & 3 deletions invites/tests.py

This file was deleted.

7 changes: 0 additions & 7 deletions invites/urls.py

This file was deleted.

49 changes: 0 additions & 49 deletions invites/views.py

This file was deleted.

1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,4 @@ traitlets==5.14.3
typing_extensions==4.12.2
tzdata==2024.1
wcwidth==0.2.13
strenum==0.4.15
7 changes: 3 additions & 4 deletions survey/admin.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
from django.contrib import admin
from .models import Questionnaire, Question, Answer
from .models import Survey, SurveyResponse

admin.site.register(Questionnaire)
admin.site.register(Question)
admin.site.register(Answer)
admin.site.register(Survey)
admin.site.register(SurveyResponse)
100 changes: 61 additions & 39 deletions survey/forms.py
Original file line number Diff line number Diff line change
@@ -1,40 +1,62 @@
from django import forms
from .models import Answer, Question
class AnswerForm(forms.ModelForm):
class Meta:
model = Answer
fields = [] # no defaults needed

def __init__(self, *args, **kwargs):
questionnaire = kwargs.pop('questionnaire', None) # get the questionnaire passed in
super().__init__(*args, **kwargs)

if questionnaire:

for index, question in enumerate(questionnaire.questions.all(), start=1):
if question.question_type == 'boolean':
self.fields[f'question_{question.id}'] = forms.ChoiceField(
label=f"{index}. {question.question_text}",
choices=[('agree', 'I agree'), ('disagree', 'I disagree')],
widget=forms.RadioSelect,
required=True
)

elif question.question_type == 'rating':

self.fields[f'question_{question.id}'] = forms.ChoiceField(
label=question.question_text,
choices=[(i, str(i)) for i in range(1, 6)], # assuming a 1-5 rating
required=True
)


else:

pass

# self.fields[f'question_{question.id}'] = forms.CharField(
# label=question.question_text,
# required=True,
# widget=forms.Textarea(attrs={'rows': 4, 'style': 'width: 80%;'}),
# )
from django.forms import BaseFormSet, formset_factory
from strenum import StrEnum
from django.core.validators import EmailValidator

class InvitationForm(forms.Form):
email = forms.EmailField(label='Participant Email',
max_length=100,
required=True,
validators=[EmailValidator()])

class FormFieldType(StrEnum):
CHAR = "char"
TEXT = "text"
RADIO = "radio"
CHECKBOX = "checkbox"
LIKERT = "likert"



def create_field_from_config(field_config: dict):
"""
Convert a field configuration into the correct django field
"""
if field_config['type'] == FormFieldType.CHAR:
field = forms.CharField(label=field_config["label"])
elif field_config['type'] == FormFieldType.TEXT:
field = forms.CharField(label=field_config["label"],
widget=forms.Textarea)
elif field_config['type'] == FormFieldType.RADIO:
field = forms.ChoiceField(label=field_config["label"],
choices=field_config["options"],
widget=forms.RadioSelect)
elif field_config['type'] == FormFieldType.CHECKBOX:
field = forms.MultipleChoiceField(label=field_config["label"],
widget=forms.CheckboxSelectMultiple,
choices=field_config["options"])
else:
field = forms.CharField(label=field_config["label"],
widget=forms.Textarea)

if "required" in field_config:
field.required = field_config["required"]

return field



def create_dynamic_formset(field_configs: list):
"""
Create a dynamic form set from a list of field configurations.
"""
class BlankDynamicForm(forms.Form):
pass

class BaseTestFormSet(BaseFormSet):
def add_fields(self, form, index):
super().add_fields(form, index)
for field_config in field_configs:
form.fields[field_config["name"]] = create_field_from_config(field_config)

return formset_factory(BlankDynamicForm, BaseTestFormSet, min_num=1, max_num=1)
Loading

0 comments on commit dc53e6d

Please sign in to comment.