Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add dynamic form generation #31

Open
wants to merge 1 commit into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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