Vlad Ivanyk
Vlad Ivanyk

Reputation: 57

Django Dynamic Nested Formsets

I have 3 models Clinic, Doctor, DoctorHours I want to create a dynamic form which will allow me to create those instances in one form something like this:

-ClinicForm

--add_doctor_button

--DoctorForm

----add_doctor_hours_button

----DoctorHoursForm

----DoctorHoursForm

--DoctorForm

----add_doctor_hours_button

----DoctorHoursForm

----DoctorHoursForm

----DoctorHoursForm

Please help

My best try:

view:

class CreatePracticeFormView(FormView):
    template_name = 'admin/practices/create_form.html'
    form_class = PracticeCreateForm
    success_url = '/admin/emr/practice/'

    def form_valid(self, form):

        print(self.request.POST)

        return super().form_valid(form)

forms:

class DoctorWorkingHoursForm(forms.Form):

    week_day = forms.ChoiceField(choices=DoctorWorkingHours.WeekDay.choices)
    start_time = forms.TimeField(required=True)
    end_time = forms.TimeField()


DoctorWorkingHoursFormSet = forms.formset_factory(DoctorWorkingHoursForm, extra=0)


class DoctorCreateForm(forms.Form):

    first_name = forms.CharField(required=True)
    last_name = forms.CharField()
    npi = forms.EmailField()
    specialty = forms.ModelChoiceField(queryset=Speciality.objects.all())
    credentials = forms.CharField()
    hours = DoctorWorkingHoursFormSet()

DoctorCreateFormSet = forms.formset_factory(DoctorCreateForm, extra=0)

class PracticeCreateForm(forms.Form):

    name = forms.CharField()
    type = forms.CharField()
    primary_contact_name = forms.CharField()
    ehr = forms.ModelChoiceField(queryset=EHR.objects.all())
    scheduling_extension = forms.ModelChoiceField(queryset=SchedulingExtension.objects.all())
    primary_visit_type = forms.ModelChoiceField(queryset=VisitType.objects.all())
    secondary_visit_type = forms.ModelChoiceField(queryset=VisitType.objects.all())
    doctors = DoctorCreateFormSet()

DoctorCreateFormSet = forms.formset_factory(DoctorCreateForm, extra=0, formset=BaseDoctorCreateFormset)

Here what I get is the forms in template where I can dynamically add DoctorForm and HourForm with jQuery and get that data in the view

but how to validate and assemble this data into objects it is the big question

Upvotes: 1

Views: 233

Answers (1)

Daniel Morell
Daniel Morell

Reputation: 2596

This is a simple example of what you could do. It is not exactly nested. But it will provide most of the functionality you are looking for.

# admin.py
from django.contrib import admin
from .models import Clinic, Doctor, DoctorHours


class DoctorHoursInline(admin.TabularInline):
    model = DoctorHours


@admin.register(Doctor)
class DoctorAdmin(admin.ModelAdmin):
    # stuff
    inlines = [DoctorHoursInline,]
    # more stuff


class DoctorInline(admin.TabularInline):
    model = Doctor

    # This will show a link to edit the Doctor model
    # in the Doctor table of the Clinic change form.
    show_change_link = True 


@admin.register(Clinic)
class ClinicAdmin(admin.ModelAdmin):
    # stuff
    inlines = [DoctorInline,]
    # more stuff

You may of course want to swap out the forms on each of these ModelAdmin and TabularInline classes.

Docs: https://docs.djangoproject.com/en/4.0/ref/contrib/admin/#inlinemodeladmin-objects

Upvotes: 1

Related Questions