Attendance system using Django
Asked Answered
M

1

1

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())
        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(request.POST)
        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/')

Forms

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

AttendanceFormset = modelformset_factory(Attendance,fields=('attendance',))

Template

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

The webapp has a login feature. The headofdepartment can mark the attendance . List of employees are rendered in the template without any issues , I want to mark attendance to the respective employees sorted in ascending order of their first_name .

That is when marking attendance employees will be listed in template, and to the right attendance form will be displayed for all the employees . It is saving only one object and not assigning the initial value for employee

Requirement :

enter image description here

Montgomery answered 27/5, 2019 at 11:26 Comment(8)
Django class-based views tackle very common things, but don't solve everything. The CreateView is for one object. As you say, you need a view that implements a modelformset (or maybe even an inlinemodelformset), so create your own view for that.Creature
but is there a way to pass the rendered list of employees as employee in the attendance form ? I am unaware writing a model formset in such a way that it accepts the rendered list employees as the form valueMontgomery
Just look at the docs. You need to create the forms with the initial values already set for each employee. You don't "pass the rendered list of employees...".Creature
I followed the docs and used initial (updated the question ) , but it's not assigning the initial value to attendance and only saving one object . In this for about 5 daysMontgomery
Is AttendanceFormset created with the inlineformset_factory? Then when you instantiate the formset, you need to set initial: formset = AttendanceFormset(instance=initial_hod, initial=[{'employee': employee} for employee in self.get_initial()['employee']) and the same for post() where you add data=request.POST.Creature
no it is done using modelformset , i have updated the question ,please checkMontgomery
You should use the inlineformset_factory, with fields 'employee' and 'attendance'. Also don't loop through the employees in your template, you only need to loop through the forms in the formset.Creature
can you help me with an answer , i would be thankful . Let us continue this discussion in chat.Montgomery
M
2

Following dirkgroten I was able to solve the issue, answer allow to render a list employees under the head_of_department(logged in hod) and mark respective attendance .

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
    form_class = Attendanceform
    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=self.request.user.email), initial=[{'employee': employee} for employee in self.get_initial()['employee']])
        return context

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

    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)

    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/')

Forms

class Attendanceform(ModelForm):
    class Meta:
        model = Attendance
        widgets = {'employee' : HiddenInput}
        fields = ('employee','attendance','hod')
AttendanceFormset = inlineformset_factory(Head_of_department,Attendance,form=Attendanceform,fields=('attendance','employee'))

Template

{% csrf_token %}
{{ formset.management_form }}
   {% for form in formset %}
      {{ form.employee.initial }} {{ form.employee}}  {{ form.attendance }}
<br><br>
   {% endfor %}
Montgomery answered 8/6, 2019 at 10:54 Comment(2)
What was the urls.py code or the way you called the index page?Azaleeazan
path('dashboard/attendance',views.attendance,name='attendance'), the answer is based on last years django version , but the basic working flow is known from the answerMontgomery

© 2022 - 2024 — McMap. All rights reserved.