Search code examples
pythondjangotime-and-attendance

Passing initial value in formset


Models

attendance_choices = (
    ('absent', 'Absent'),
    ('present', 'Present')
)

class Head_of_department(models.Model):
    first_name = models.CharField(max_length=200)
    last_name = models.CharField(max_length=200)
    email = models.CharField(max_length=30)

    def __str__(self):
        return self.first_name 

class Employee(models.Model):
    first_name = models.CharField(max_length=200, unique=True)
    last_name = models.CharField(max_length=200, unique=True)
    head_of_department = models.ForeignKey('Head_of_department', on_delete=models.SET_NULL, blank=True, null=True)
    email = models.EmailField(max_length=100)

     def __str__(self):
        return self.first_name + ' ' + self.last_name

class Attendance(models.Model):
    head_of_department = models.ForeignKey('Head_of_department', on_delete=models.SET_NULL, blank=True, null=True)
    employee = models.ForeignKey('Employee', on_delete=models.CASCADE, )
    attendance = models.CharField(max_length=8, choices=attendance_choices, blank=True)

Views

class Attendancecreate(CreateView):
    model = Attendance
    fields = ['employee']
    success_url = '/dashboard/'

    def get_context_data(self,** kwargs):
        context = super(Attendancecreate, self).get_context_data(**kwargs)
        context['formset'] = AttendanceFormset(queryset=Attendance.objects.none(), instance=Head_of_department.objects.get(email=email), initial=[{'employee': employee} for employee inself.get_initial()['employee']])
        context['attendance_form'] = Attendanceform()
        email = self.request.user.email
        hod = Head_of_department.objects.get(email=email)
        context["employees"] = Employee.objects.filter(head_of_department =hod)
        return context

    def get_initial(self):
        email = self.request.user.email
        hod = Head_of_department.objects.get(email=email)
        initial = super(Attendancecreate , self).get_initial()
        initial['employee'] = Employee.objects.filter(head_of_department=hod)
        return initial

    def post(self, request, *args, **kwargs):
        formset = AttendanceFormset(queryset=Attendance.objects.none(), instance=Head_of_department.objects.get(email=email), initial=[{'employee': employee} for employee inself.get_initial()['employee']))
        if formset.is_valid():
            return self.form_valid(formset)

     def form_valid(self, formset):
        instances = formset.save(commit=False)
        for instance in instances:
            instance.head_of_department = get_object_or_404(Head_of_department, email=self.request.user.email)
            instance.save()
        return HttpResponseRedirect('/dashboard/')
     def form_invalid(self, formset):
        print ('errors')
        print (formset.errors)

Forms

class Attendanceform(ModelForm):
    class Meta:
        model = Attendance
        fields = ('employee','attendance','hod')

AttendanceFormset = inlineformset_factory(Head_of_department,Attendance,fields=('attendance',))

Template

{% csrf_token %}
{{ formset.management_form }}
{% for form in formset %}
{{ form }}
<br><br>
{% endfor %}

Error

Below shown square brackets was printed in the console when I used print(formset.errors)

[]

How to pass employees as initial values for attendance model as shown below in the images, employees will be rendered and rendered values have to be passed as employee in attendance model.

Is there any workaround with modelformset or inlineformset ? I can't get it right with the views I have included in the question .

enter image description here


Solution

  • I was missing request.post ,

    class Attendancecreate(CreateView):
        ...
            def post(self, request, *args, **kwargs,):
            formset = AttendanceFormset(request.POST,queryset=Attendance.objects.none(), instance=Head_of_department.objects.get(email=self.request.user.email), initial=[{'employee': employee} for employee in self.get_initial()['employee']])
            if formset.is_valid():
                return self.form_valid(formset)
    
    
    

    Template

    {% csrf_token %}
    {{ formset.management_form }}
         {% for form in formset %}
              {{ form.employee.initial }} {{ form.employee}}  {{ form.attendance }}
    <br><br>
         {% endfor %}