Merge pull request #12 from benaissazaki/add-filters-to-tables

Add filters to tables
This commit is contained in:
Adil Mohak 2024-01-05 22:49:00 +03:00 committed by GitHub
commit ea75bc29dd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 88 additions and 22 deletions

71
accounts/filters.py Normal file
View File

@ -0,0 +1,71 @@
from django.db.models import Q
import django_filters
from .models import User, Student
class LecturerFilter(django_filters.FilterSet):
username = django_filters.CharFilter(lookup_expr="exact", label="")
name = django_filters.CharFilter(method="filter_by_name", label="")
email = django_filters.CharFilter(lookup_expr="icontains", label="")
class Meta:
model = User
fields = ["username", "email"]
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# Change html classes and placeholders
self.filters["username"].field.widget.attrs.update(
{"class": "au-input", "placeholder": "ID No."}
)
self.filters["name"].field.widget.attrs.update(
{"class": "au-input", "placeholder": "Name"}
)
self.filters["email"].field.widget.attrs.update(
{"class": "au-input", "placeholder": "Email"}
)
def filter_by_name(self, queryset, name, value):
return queryset.filter(
Q(first_name__icontains=value) | Q(last_name__icontains=value)
)
class StudentFilter(django_filters.FilterSet):
student__username = django_filters.CharFilter(lookup_expr="exact", label="")
student__name = django_filters.CharFilter(method="filter_by_name", label="")
student__email = django_filters.CharFilter(lookup_expr="icontains", label="")
department__title = django_filters.CharFilter(lookup_expr="icontains", label="")
class Meta:
model = Student
fields = [
"student__username",
"student__name",
"student__email",
"department__title",
]
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# Change html classes and placeholders
self.filters["student__username"].field.widget.attrs.update(
{"class": "au-input", "placeholder": "ID No."}
)
self.filters["student__name"].field.widget.attrs.update(
{"class": "au-input", "placeholder": "Name"}
)
self.filters["student__email"].field.widget.attrs.update(
{"class": "au-input", "placeholder": "Email"}
)
self.filters["department__title"].field.widget.attrs.update(
{"class": "au-input", "placeholder": "Department"}
)
def filter_by_name(self, queryset, name, value):
return queryset.filter(
Q(student__first_name__icontains=value)
| Q(student__last_name__icontains=value)
)

View File

@ -14,7 +14,7 @@ from .views import (
admin_panel, admin_panel,
profile_update, profile_update,
change_password, change_password,
LecturerListView, LecturerFilterView,
StudentListView, StudentListView,
staff_add_view, staff_add_view,
edit_staff, edit_staff,
@ -37,7 +37,7 @@ urlpatterns = [
path("profile/<int:id>/detail/", profile_single, name="profile_single"), path("profile/<int:id>/detail/", profile_single, name="profile_single"),
path("setting/", profile_update, name="edit_profile"), path("setting/", profile_update, name="edit_profile"),
path("change_password/", change_password, name="change_password"), path("change_password/", change_password, name="change_password"),
path("lecturers/", LecturerListView.as_view(), name="lecturer_list"), path("lecturers/", LecturerFilterView.as_view(), name="lecturer_list"),
path("lecturer/add/", staff_add_view, name="add_lecturer"), path("lecturer/add/", staff_add_view, name="add_lecturer"),
path("staff/<int:pk>/edit/", edit_staff, name="staff_edit"), path("staff/<int:pk>/edit/", edit_staff, name="staff_edit"),
path("lecturers/<int:pk>/delete/", delete_staff, name="lecturer_delete"), path("lecturers/<int:pk>/delete/", delete_staff, name="lecturer_delete"),

View File

@ -7,12 +7,14 @@ from django.views.generic import CreateView, ListView
from django.db.models import Q from django.db.models import Q
from django.utils.decorators import method_decorator from django.utils.decorators import method_decorator
from django.contrib.auth.forms import PasswordChangeForm from django.contrib.auth.forms import PasswordChangeForm
from django_filters.views import FilterView
from core.models import Session, Semester from core.models import Session, Semester
from course.models import Course from course.models import Course
from result.models import TakenCourse from result.models import TakenCourse
from .decorators import admin_required from .decorators import admin_required
from .forms import StaffAddForm, StudentAddForm, ProfileUpdateForm, ParentAddForm from .forms import StaffAddForm, StudentAddForm, ProfileUpdateForm, ParentAddForm
from .models import User, Student, Parent from .models import User, Student, Parent
from .filters import LecturerFilter, StudentFilter
def validate_username(request): def validate_username(request):
@ -259,7 +261,8 @@ def edit_staff(request, pk):
@method_decorator([login_required, admin_required], name="dispatch") @method_decorator([login_required, admin_required], name="dispatch")
class LecturerListView(ListView): class LecturerFilterView(FilterView):
filterset_class = LecturerFilter
queryset = User.objects.filter(is_lecturer=True) queryset = User.objects.filter(is_lecturer=True)
template_name = "accounts/lecturer_list.html" template_name = "accounts/lecturer_list.html"
paginate_by = 10 # if pagination is desired paginate_by = 10 # if pagination is desired
@ -348,16 +351,10 @@ def edit_student(request, pk):
@method_decorator([login_required, admin_required], name="dispatch") @method_decorator([login_required, admin_required], name="dispatch")
class StudentListView(ListView): class StudentListView(FilterView):
filterset_class = StudentFilter
template_name = "accounts/student_list.html" template_name = "accounts/student_list.html"
paginate_by = 10 # if pagination is desired paginate_by = 10
def get_queryset(self):
queryset = Student.objects.all()
query = self.request.GET.get("student_id")
if query is not None:
queryset = queryset.filter(Q(department=query))
return queryset
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs) context = super().get_context_data(**kwargs)

View File

@ -49,6 +49,7 @@ DJANGO_APPS = [
THIRD_PARTY_APPS = [ THIRD_PARTY_APPS = [
"crispy_forms", "crispy_forms",
"rest_framework", "rest_framework",
"django_filters",
] ]
# Custom apps # Custom apps

View File

@ -15,6 +15,7 @@ django-crispy-forms==1.14.0 # https://github.com/django-crispy-forms/django-cri
crispy-bootstrap5==0.7 # https://github.com/django-crispy-forms/crispy-bootstrap5 crispy-bootstrap5==0.7 # https://github.com/django-crispy-forms/crispy-bootstrap5
django-compressor==4.1 # https://github.com/django-compressor/django-compressor django-compressor==4.1 # https://github.com/django-compressor/django-compressor
django-redis==5.2.0 # https://github.com/jazzband/django-redis django-redis==5.2.0 # https://github.com/jazzband/django-redis
django-filter==23.5 # https://github.com/carltongibson/django-filter
# Django REST Framework # Django REST Framework
djangorestframework==3.14.0 # https://github.com/encode/django-rest-framework djangorestframework==3.14.0 # https://github.com/encode/django-rest-framework
django-cors-headers==3.13.0 # https://github.com/adamchainz/django-cors-headers django-cors-headers==3.13.0 # https://github.com/adamchainz/django-cors-headers

View File

@ -29,11 +29,9 @@
<div class="content-center"> <div class="content-center">
<form class="search-form" action="" method="get"> <form class="search-form" action="" method="get">
<input class="au-input" type="text" name="id_no" placeholder="ID No." value="{{ request.GET.id_no }}"/> {{ filter.form }}
<input class="au-input" type="text" name="name" placeholder="Name" value="{{ request.GET.name }}"/>
<input class="au-input" type="text" name="email" placeholder="Email" value="{{ request.GET.email }}"/>
<button class="btn btn-light" type="submit"> <button class="btn btn-light" type="submit">
<i class="fas fa-search"></i> filter <i class="fas fa-search"></i> Filter
</button> </button>
</form> </form>
</div> </div>
@ -55,7 +53,7 @@
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{% for lecturer in object_list %} {% for lecturer in filter.qs %}
<tr> <tr>
<td> {{ forloop.counter }}.</td> <td> {{ forloop.counter }}.</td>
<td>{{ lecturer.username }}</td> <td>{{ lecturer.username }}</td>

View File

@ -29,11 +29,9 @@
<div class="content-center"> <div class="content-center">
<form class="search-form" action="" method="get"> <form class="search-form" action="" method="get">
<input class="au-input" type="text" id="student_id" name="student_id" placeholder="ID No." value="{{ request.GET.student_id }}"/> {{ filter.form }}
<input class="au-input" type="text" name="name" placeholder="Name" value="{{ request.GET.name }}"/>
<input class="au-input" type="text" name="department" placeholder="Department" value="{{ request.GET.department }}"/>
<button class="btn btn-light" type="submit"> <button class="btn btn-light" type="submit">
<i class="fas fa-search"></i> filter <i class="fas fa-search"></i> Filter
</button> </button>
</form> </form>
</div> </div>
@ -63,7 +61,7 @@
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{% for student in object_list %} {% for student in filter.qs %}
<tr> <tr>
<td> {{ forloop.counter }}.</td> <td> {{ forloop.counter }}.</td>
<td>{{ student.student.username }} </td> <td>{{ student.student.username }} </td>