1

Thank you all for always sharing your knowledge here.

I have an issue with counting an object in Django. I am currently learning and working on a basic HR system and already have my views, models, et al set up. I plan to have an interface whereby I can print out employees count based on gender. The one I currently have set up is increasing the counts for both male and female any time I create a new employee. Please how do I correct this anomaly?

views.py

from django.contrib.auth.decorators import login_required
from django.contrib.auth.models import User
from django.shortcuts import render
from django_tables2 import RequestConfig
from django_tables2.export import TableExport

from .models import Employee
from .models import EmployeeFilter
from .tables import EmployeeTable

@login_required()
def employees(request):
    filter = EmployeeFilter(request.GET, queryset=Employee.objects.all())
    table = EmployeeTable(filter.qs)
    RequestConfig(request, paginate={"per_page": 15}).configure(table)
    count = Employee.objects.all().count()
    male_count = Employee.objects.filter(gender__contains='Male').count()
    female_count = Employee.objects.filter(gender__contains='Female').count()
    user_count = User.objects.all().count()

    export_format = request.GET.get("_export", None)

    if TableExport.is_valid_format(export_format):
        exporter = TableExport(export_format, table)
        return exporter.response("table.{}".format("csv", "xlsx"))

    return render(request, "employees/employees.html", {
        "table": table,
        "filter": filter,
        "count": count,
        "male_count": male_count,
        "female_count": female_count,
        "user_count": user_count,
    })

template.html

{% extends "employees/base.html" %}
{% load render_table from django_tables2 %}
{% load django_tables2 %}
{% load querystring from django_tables2 %}
{% block content %}
<!--Data overview-->
    <div class="container data overview">
        <div class="row">
            <div class="col-md-3">
                <div class="container-fluid bg-warning data-ov-container">
                    <div class="row">
                        <div class="col-8">
                            <h6 class="data-heading font-weight-bold">Total Employees</h6>
                            <p class="data-text ">{{ count }}</p>
                        </div>

                        <div class="col-4">
                            <i class="fas fa-users data-icon"></i>
                        </div>
                    </div>
                </div>
            </div>

            <div class="col-md-3">
                <div class="container-fluid bg-dark data-ov-container">
                    <div class="row">
                        <div class="col-9">
                            <h6 class="data-heading text-white font-weight-bold">Male Employees</h6>
                            <p class="data-text text-white">{{ male_count }}</p>
                        </div>

                        <div class="col-3">
                            <i class="fas fa-male data-icon text-white"></i>
                        </div>
                    </div>
                </div>
            </div>

            <div class="col-md-3">
                <div class="container-fluid bg-danger data-ov-container">
                    <div class="row">
                        <div class="col-9">
                            <h6 class="data-heading text-white font-weight-bold">Female Employees</h6>
                            <p class="data-text text-white">{{ female_count }}</p>
                        </div>

                        <div class="col-3">
                            <i class="fas fa-female data-icon text-white"></i>
                        </div>
                    </div>
                </div>
            </div>

            <div class="col-md-3">
                <div class="container-fluid bg-secondary data-ov-container">
                    <div class="row">
                        <div class="col-8">
                            <h6 class="data-heading text-white font-weight-bold">Active Users</h6>
                            <p class="data-text text-white">{{ user_count }}</p>
                        </div>

                        <div class="col-4">
                            <i class="fas fa-users-cog data-icon text-white"></i>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>

    <!--Employees data-->
    <div class="filter-container container-fluid">
        <div class="row">
            <div class="col-md-9">
                <!--filter form-->
                <form action="" class="form form-inline employee-filter-form" method="get">
                    <legend class="mb-2">Filter employee records</legend>
                    {{ form.non_field_errors }}
                    <div class="fieldWrapper">
                        {{ filter.form.first_name.errors }}
                        {{ filter.form.first_name }}
                    </div>
                    <div class="fieldWrapper">
                        {{ filter.form.last_name.errors }}
                        {{ filter.form.last_name }}
                    </div>
                    <button aria-expanded="false" aria-haspopup="true"
                            class="ml-2 btn btn-danger filter-btn" type="submit">
                        Filter
                    </button>
                </form>
            </div>

            <div class="col-md-3 download-btn-col">
                <button aria-expanded="false" aria-haspopup="true"
                        class="mr-3 btn btn-success" type="submit">
                    <i class="fas fa-upload"></i> Import
                </button>
                <div class="btn-group download-btn">
                    <button aria-expanded="false" aria-haspopup="true"
                            class="btn btn-warning dropdown-toggle"
                            data-toggle="dropdown" type="button">
                        <i class="fas fa-file-export"></i> Export
                    </button>
                    <div class="dropdown-menu">
                        <a class="dropdown-item" href="{% querystring '_export'='csv' %}">csv</a>
                        <a class="dropdown-item" href="{% querystring '_export'='xlsx' %}">xlsx</a>
                    </div>
                </div>
            </div>
        </div>
    </div>
    <!-- data rendered here -->
    {% render_table table 'django_tables2/bootstrap.html' %}
    <!-- data rendered here -->
    {% endblock content %}

models.py

...
GENDER_CHOICES = (
    ('FEMALE', 'Female'),
    ('MALE', 'Male'),
    ("DWTS" "Don't want to say"),
)
...
@python_2_unicode_compatible
class Employee(models.Model):
    # basic information of employee
    first_name = models.CharField(_('first name'), max_length=40)
    last_name = models.CharField(_('last name'), max_length=40)
    emp_photo = models.ImageField(_('passport'))
    date_of_birth = models.DateField(_('birthday'))
    gender = models.CharField(_('gender'), max_length=15, choices=GENDER_CHOICES, default=['MALE', 'Male'])
    house_address = models.CharField(_('house address'), max_length=100)
    city_of_residence = models.CharField(_('city'), max_length=100)
    state_of_residence = models.CharField(_('state'), max_length=100, choices=NIGERIAN_STATE_CHOICES)
    country_of_residence = models.CharField(_('country'), max_length=100, choices=COUNTRY_CHOICES,
                                            default=[156, 'Nigeria'])
    state_of_origin = models.CharField(_('state of origin'), max_length=100, choices=NIGERIAN_STATE_CHOICES)

    class Meta:
        verbose_name = _('Employee')
        verbose_name_plural = _('Employees')

    def __str__(self):
        return "{} {}".format(self.first_name, self.last_name)

@python_2_unicode_compatible
class EmployeeFilter(django_filters.FilterSet):
    first_name = django_filters.CharFilter(lookup_expr='iexact', widget=TextInput(
        attrs={'placeholder': 'First name', 'class': 'input_search'}))
    last_name = django_filters.CharFilter(lookup_expr='iexact',
                                          widget=TextInput(attrs={'placeholder': 'Last name', 'class': 'input_search'}))

    class Meta:
        model = Employee
        fields = ["first_name", "last_name", ]
7
  • Django actually support this with signal you can create a post_save on a model to handle whenever an object is create to do some function Commented Dec 5, 2019 at 9:06
  • Show your models. It seems odd to use a __contains filter there. (And separately, please consider why you need to record gender at all, especially with those two specific options.) Commented Dec 5, 2019 at 9:10
  • Thank you guys. @Daniel I have added the models Commented Dec 5, 2019 at 9:16
  • And what is GENDER_CHOICES? Also note, the default there doesn't make sense, why would it be a list? Commented Dec 5, 2019 at 9:23
  • Okay @Daniel. I have added the gender choices. Thanks for bringing my attention to that default ish, I get your point. What do you suggest as the best approach? Commented Dec 5, 2019 at 9:32

1 Answer 1

1

I think you need to remove contains from your filter:

male_count = Employee.objects.filter(gender='Male').count()
female_count = Employee.objects.filter(gender='Female').count()

Or make a single request:

male_femail_count = Employee.objects.values('gender').annotate(count=Count('id'))
# result
# [{'gender': 'Male', 'count': 2}, {'gender': 'Female', 'count': 3}]
Sign up to request clarification or add additional context in comments.

1 Comment

Thank you also @Sergey. Your solution worked after I made some basic modifications to my items, i.e "Male" to "MALE", being the first item on the element.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.