Skip to content

Commit 91264d8

Browse files
committed
filter by user type
1 parent fffc0e0 commit 91264d8

File tree

2 files changed

+90
-54
lines changed

2 files changed

+90
-54
lines changed

codeforlife/user/filters/user.py

Lines changed: 31 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,12 @@
1212
)
1313

1414
from ...filters import FilterSet # isort: skip
15-
from ..models import User # isort: skip
15+
from ..models import ( # isort: skip
16+
User,
17+
TeacherUser,
18+
StudentUser,
19+
IndependentUser,
20+
)
1621

1722

1823
# pylint: disable-next=missing-class-docstring
@@ -22,14 +27,22 @@ class UserFilterSet(FilterSet):
2227
"exact",
2328
)
2429

25-
_id = filters.NumberFilter(method="_id_method")
26-
_id_method = FilterSet.make_exclude_field_list_method("id")
30+
_id = filters.NumberFilter(method="_id__method")
31+
_id__method = FilterSet.make_exclude_field_list_method("id")
2732

28-
name = filters.CharFilter(method="name_method")
33+
name = filters.CharFilter(method="name__method")
2934

30-
only_teachers = filters.BooleanFilter(method="only_teachers__method")
35+
type = filters.ChoiceFilter(
36+
choices=[
37+
("teacher", "teacher"),
38+
("student", "student"),
39+
("independent", "independent"),
40+
("indy", "independent"),
41+
],
42+
method="type__method",
43+
)
3144

32-
def name_method(
45+
def name__method(
3346
self: FilterSet, queryset: QuerySet[User], name: str, *args
3447
):
3548
"""Get all first names and last names that contain a substring."""
@@ -45,16 +58,19 @@ def name_method(
4558
| Q(last_name__icontains=last_name)
4659
)
4760

48-
def only_teachers__method(
49-
self: FilterSet, queryset: QuerySet[User], _: str, value: bool
61+
def type__method(
62+
self: FilterSet,
63+
queryset: QuerySet[User],
64+
_: str,
65+
value: t.Literal["teacher", "student", "independent"],
5066
):
51-
"""Get only teacher-users."""
52-
return (
53-
queryset.filter(new_teacher__isnull=False, new_student__isnull=True)
54-
if value
55-
else queryset
56-
)
67+
"""Get users of a specific type."""
68+
if value == "teacher":
69+
return TeacherUser.objects.filter_users(queryset)
70+
if value == "student":
71+
return StudentUser.objects.filter_users(queryset)
72+
return IndependentUser.objects.filter_users(queryset)
5773

5874
class Meta:
5975
model = User
60-
fields = ["students_in_class", "only_teachers", "_id", "name"]
76+
fields = ["students_in_class", "type", "_id", "name"]

codeforlife/user/models/user.py

Lines changed: 59 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111

1212
# pylint: disable-next=imported-auth-user
1313
from django.contrib.auth.models import User as _User
14-
from django.contrib.auth.models import UserManager
14+
from django.contrib.auth.models import UserManager as _UserManager
1515
from django.db.models import F
1616
from django.db.models.query import QuerySet
1717
from django.utils.crypto import get_random_string
@@ -157,13 +157,28 @@ def anonymize(self):
157157
AnyUser = t.TypeVar("AnyUser", bound=User)
158158

159159

160-
# pylint: disable-next=missing-class-docstring,too-few-public-methods
161-
class ContactableUserManager(UserManager[AnyUser], t.Generic[AnyUser]):
160+
# pylint: disable-next=missing-class-docstring
161+
class UserManager(_UserManager[AnyUser], t.Generic[AnyUser]):
162+
def filter_users(self, queryset: QuerySet[User]):
163+
"""Filter the users to the specific type.
164+
165+
Args:
166+
queryset: The queryset of users to filter.
167+
168+
Returns:
169+
A subset of the queryset of users.
170+
"""
171+
return queryset
172+
162173
# pylint: disable-next=missing-function-docstring
163174
def get_queryset(self):
164-
return (
165-
super().get_queryset().exclude(email__isnull=True).exclude(email="")
166-
)
175+
return self.filter_users(super().get_queryset())
176+
177+
178+
# pylint: disable-next=missing-class-docstring,too-few-public-methods
179+
class ContactableUserManager(UserManager[AnyUser], t.Generic[AnyUser]):
180+
def filter_users(self, queryset: QuerySet[User]):
181+
return queryset.exclude(email__isnull=True).exclude(email="")
167182

168183

169184
class ContactableUser(User):
@@ -238,15 +253,16 @@ def create_user( # type: ignore[override]
238253

239254
return user
240255

241-
# pylint: disable-next=missing-function-docstring
242-
def get_queryset(self):
256+
def filter_users(self, queryset: QuerySet[User]):
243257
return (
244258
super()
245-
.get_queryset()
259+
.filter_users(queryset)
246260
.filter(new_teacher__isnull=False, new_student__isnull=True)
247-
.prefetch_related("new_teacher")
248261
)
249262

263+
def get_queryset(self):
264+
return super().get_queryset().prefetch_related("new_teacher")
265+
250266

251267
class TeacherUser(ContactableUser):
252268
"""A user that is a teacher."""
@@ -287,9 +303,12 @@ def create_user( # type: ignore[override]
287303
**extra_fields,
288304
)
289305

290-
# pylint: disable-next=missing-function-docstring
291-
def get_queryset(self):
292-
return super().get_queryset().filter(new_teacher__school__isnull=False)
306+
def filter_users(self, queryset: QuerySet[User]):
307+
return (
308+
super()
309+
.filter_users(queryset)
310+
.filter(new_teacher__school__isnull=False)
311+
)
293312

294313

295314
# pylint: disable-next=too-many-ancestors
@@ -317,9 +336,8 @@ def teacher(self):
317336
class AdminSchoolTeacherUserManager(
318337
SchoolTeacherUserManager["AdminSchoolTeacherUser"]
319338
):
320-
# pylint: disable-next=missing-function-docstring
321-
def get_queryset(self):
322-
return super().get_queryset().filter(new_teacher__is_admin=True)
339+
def filter_users(self, queryset: QuerySet[User]):
340+
return super().filter_users(queryset).filter(new_teacher__is_admin=True)
323341

324342

325343
# pylint: disable-next=too-many-ancestors
@@ -347,9 +365,10 @@ def teacher(self):
347365
class NonAdminSchoolTeacherUserManager(
348366
SchoolTeacherUserManager["NonAdminSchoolTeacherUser"]
349367
):
350-
# pylint: disable-next=missing-function-docstring
351-
def get_queryset(self):
352-
return super().get_queryset().filter(new_teacher__is_admin=False)
368+
def filter_users(self, queryset: QuerySet[User]):
369+
return (
370+
super().filter_users(queryset).filter(new_teacher__is_admin=False)
371+
)
353372

354373

355374
# pylint: disable-next=too-many-ancestors
@@ -377,9 +396,12 @@ def teacher(self):
377396

378397
# pylint: disable-next=missing-class-docstring,too-few-public-methods
379398
class NonSchoolTeacherUserManager(TeacherUserManager["NonSchoolTeacherUser"]):
380-
# pylint: disable-next=missing-function-docstring
381-
def get_queryset(self):
382-
return super().get_queryset().filter(new_teacher__school__isnull=True)
399+
def filter_users(self, queryset: QuerySet[User]):
400+
return (
401+
super()
402+
.filter_users(queryset)
403+
.filter(new_teacher__school__isnull=True)
404+
)
383405

384406

385407
# pylint: disable-next=too-many-ancestors
@@ -440,20 +462,17 @@ def create_user( # type: ignore[override]
440462

441463
return user
442464

443-
# pylint: disable-next=missing-function-docstring
444-
def get_queryset(self):
445-
return (
446-
super()
447-
.get_queryset()
448-
.filter(
449-
new_teacher__isnull=True,
450-
new_student__isnull=False,
451-
# TODO: remove in new model
452-
new_student__class_field__isnull=False,
453-
)
454-
.prefetch_related("new_student")
465+
def filter_users(self, queryset: QuerySet[User]):
466+
return queryset.filter(
467+
new_teacher__isnull=True,
468+
new_student__isnull=False,
469+
# TODO: remove in new model
470+
new_student__class_field__isnull=False,
455471
)
456472

473+
def get_queryset(self):
474+
return super().get_queryset().prefetch_related("new_student")
475+
457476

458477
class StudentUser(User):
459478
"""A user that is a student."""
@@ -509,20 +528,21 @@ def set_password(self, raw_password: t.Optional[str] = None):
509528

510529
# pylint: disable-next=missing-class-docstring,too-few-public-methods
511530
class IndependentUserManager(ContactableUserManager["IndependentUser"]):
512-
# pylint: disable-next=missing-function-docstring
513-
def get_queryset(self):
514-
# TODO: student__isnull=True in new model
531+
def filter_users(self, queryset: QuerySet[User]):
515532
return (
516533
super()
517-
.get_queryset()
534+
.filter_users(queryset)
518535
.filter(
519536
new_teacher__isnull=True,
537+
# TODO: student__isnull=True in new model
520538
new_student__isnull=False,
521539
new_student__class_field__isnull=True,
522540
)
523-
.prefetch_related("new_student")
524541
)
525542

543+
def get_queryset(self):
544+
return super().get_queryset().prefetch_related("new_student")
545+
526546
def create_user( # type: ignore[override]
527547
self,
528548
first_name: str,

0 commit comments

Comments
 (0)