From 859d724c34c51fcc79657dac1db1d864c38521aa Mon Sep 17 00:00:00 2001 From: TitouanDor Date: Sat, 20 Jun 2026 13:45:52 +0200 Subject: [PATCH 1/6] ajout requette api nouveau et ancien membre de club --- club/api.py | 52 +++++++++++++++++++++++++++++++++++++++++++++++++ club/schemas.py | 6 ++++++ 2 files changed, 58 insertions(+) diff --git a/club/api.py b/club/api.py index 4a055e2c..52acb67a 100644 --- a/club/api.py +++ b/club/api.py @@ -11,6 +11,7 @@ from club.models import Club, Membership from club.schemas import ( ClubSchema, ClubSearchFilterSchema, + MembershipFilterSchema, SimpleClubSchema, UserMembershipSchema, ) @@ -62,3 +63,54 @@ class UserClubController(ControllerBase): .filter(user=user) .select_related("club", "user", "role") ) + + +@api_controller("/club_members/{since_date}") +class ClubMembersController(ControllerBase): + @route.get( + "/new", + response=list[UserMembershipSchema], + auth=[ApiKeyAuth(), SessionAuth()], + permissions=[HasPerm("club.view_club")], + url_name="get_new_club_members_since_date", + ) + def fetch_new_club_members(self, filters: Query[MembershipFilterSchema]): + """give all the members of a club that have joined since a given date""" + memberships = Membership.objects.ongoing().filter( + start_date__gte=filters.since_date, end_date__isnull=True + ) + club_ids = memberships.values_list("club_id") + clubs = Club.objects.filter(id__in=club_ids) + return [ + { + "club": club, + "user": membership.user, + "role": membership.role, + "joined_at": membership.start_date, + } + for club in clubs + for membership in memberships.filter(club=club) + ] + + @route.get( + "/former", + response=list[UserMembershipSchema], + auth=[ApiKeyAuth(), SessionAuth()], + permissions=[HasPerm("club.view_club")], + url_name="get_former_club_members_since_date", + ) + def fetch_former_club_members(self, filters: Query[MembershipFilterSchema]): + """give all the former members of a club that have left since a given date""" + memberships = Membership.objects.filter(end_date__gte=filters.since_date) + club_ids = memberships.values_list("club_id") + clubs = Club.objects.filter(id__in=club_ids) + return [ + { + "club": club, + "user": membership.user, + "role": membership.role, + "left_at": membership.end_date, + } + for club in clubs + for membership in memberships.filter(club=club) + ] diff --git a/club/schemas.py b/club/schemas.py index 99d05fc1..d2f7f455 100644 --- a/club/schemas.py +++ b/club/schemas.py @@ -1,3 +1,4 @@ +from datetime import datetime from typing import Annotated from django.db.models import Q @@ -79,3 +80,8 @@ class UserMembershipSchema(ModelSchema): club: SimpleClubSchema role: ClubRoleSchema + user: SimpleUserSchema + + +class MembershipFilterSchema(FilterSchema): + since_date: Annotated[datetime, FilterLookup("date__lte")] = None From defeef62ea04b432cc976aca488ef05e14419596 Mon Sep 17 00:00:00 2001 From: TitouanDor Date: Sat, 20 Jun 2026 15:18:08 +0200 Subject: [PATCH 2/6] =?UTF-8?q?modif=20des=20changement=20demand=C3=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- club/api.py | 48 +++++++++++++++++------------------------------- club/schemas.py | 3 ++- 2 files changed, 19 insertions(+), 32 deletions(-) diff --git a/club/api.py b/club/api.py index 52acb67a..39f1cba7 100644 --- a/club/api.py +++ b/club/api.py @@ -65,52 +65,38 @@ class UserClubController(ControllerBase): ) -@api_controller("/club_members/{since_date}") -class ClubMembersController(ControllerBase): +@api_controller("/clubs/{club_id}/members/{since_date}") +class ClubMembershipController(ControllerBase): @route.get( "/new", response=list[UserMembershipSchema], auth=[ApiKeyAuth(), SessionAuth()], permissions=[HasPerm("club.view_club")], - url_name="get_new_club_members_since_date", + url_name="get_new_clubs_members_since_date", ) def fetch_new_club_members(self, filters: Query[MembershipFilterSchema]): - """give all the members of a club that have joined since a given date""" + """give all the members of all clubs that have joined since a given date""" memberships = Membership.objects.ongoing().filter( start_date__gte=filters.since_date, end_date__isnull=True ) - club_ids = memberships.values_list("club_id") - clubs = Club.objects.filter(id__in=club_ids) - return [ - { - "club": club, - "user": membership.user, - "role": membership.role, - "joined_at": membership.start_date, - } - for club in clubs - for membership in memberships.filter(club=club) - ] + if filters.clubs_id is None: + return memberships.order_by("start_date") + + return memberships.filter(club_id__in=filters.clubs_id) @route.get( "/former", response=list[UserMembershipSchema], auth=[ApiKeyAuth(), SessionAuth()], permissions=[HasPerm("club.view_club")], - url_name="get_former_club_members_since_date", + url_name="get_former_clubs_members_since_date", ) def fetch_former_club_members(self, filters: Query[MembershipFilterSchema]): - """give all the former members of a club that have left since a given date""" - memberships = Membership.objects.filter(end_date__gte=filters.since_date) - club_ids = memberships.values_list("club_id") - clubs = Club.objects.filter(id__in=club_ids) - return [ - { - "club": club, - "user": membership.user, - "role": membership.role, - "left_at": membership.end_date, - } - for club in clubs - for membership in memberships.filter(club=club) - ] + """give all the former members of all clubs that have left since a given date""" + memberships = Membership.objects.filter( + end_date__gte=filters.since_date, + ) + if filters.clubs_id is None: + return memberships.order_by("start_date") + + return memberships.filter(club_id__in=filters.clubs_id) diff --git a/club/schemas.py b/club/schemas.py index d2f7f455..89acf9c2 100644 --- a/club/schemas.py +++ b/club/schemas.py @@ -84,4 +84,5 @@ class UserMembershipSchema(ModelSchema): class MembershipFilterSchema(FilterSchema): - since_date: Annotated[datetime, FilterLookup("date__lte")] = None + since_date: Annotated[datetime, FilterLookup("date__lte")] + clubs_id: set[int] | None = None From 73ae7666c156d02a9b234ca9c59839531b0195ca Mon Sep 17 00:00:00 2001 From: TitouanDor Date: Sun, 21 Jun 2026 18:11:37 +0200 Subject: [PATCH 3/6] ajout des tests --- club/api.py | 3 +- club/schemas.py | 4 +- club/tests/test_club_membership_controller.py | 192 ++++++++++++++++++ 3 files changed, 196 insertions(+), 3 deletions(-) create mode 100644 club/tests/test_club_membership_controller.py diff --git a/club/api.py b/club/api.py index 39f1cba7..8115e92b 100644 --- a/club/api.py +++ b/club/api.py @@ -65,7 +65,7 @@ class UserClubController(ControllerBase): ) -@api_controller("/clubs/{club_id}/members/{since_date}") +@api_controller("/clubs/members/") class ClubMembershipController(ControllerBase): @route.get( "/new", @@ -94,6 +94,7 @@ class ClubMembershipController(ControllerBase): def fetch_former_club_members(self, filters: Query[MembershipFilterSchema]): """give all the former members of all clubs that have left since a given date""" memberships = Membership.objects.filter( + start_date__lt=filters.since_date, end_date__gte=filters.since_date, ) if filters.clubs_id is None: diff --git a/club/schemas.py b/club/schemas.py index 89acf9c2..10ea2411 100644 --- a/club/schemas.py +++ b/club/schemas.py @@ -1,4 +1,4 @@ -from datetime import datetime +from datetime import date from typing import Annotated from django.db.models import Q @@ -84,5 +84,5 @@ class UserMembershipSchema(ModelSchema): class MembershipFilterSchema(FilterSchema): - since_date: Annotated[datetime, FilterLookup("date__lte")] + since_date: Annotated[date, FilterLookup("date__lte")] clubs_id: set[int] | None = None diff --git a/club/tests/test_club_membership_controller.py b/club/tests/test_club_membership_controller.py new file mode 100644 index 00000000..73268634 --- /dev/null +++ b/club/tests/test_club_membership_controller.py @@ -0,0 +1,192 @@ +from datetime import date + +from django.contrib.auth.models import Permission +from django.test import TestCase +from django.urls import reverse +from model_bakery import baker + +from club.models import Club, ClubRole, Membership +from core.baker_recipes import subscriber_user +from core.models import User + + +class TestMembershipAPI(TestCase): + @classmethod + def setUpTestData(cls): + cls.user = baker.make(User) + perm = Permission.objects.get(codename="view_club") + cls.user.user_permissions.add(perm) + cls.clubs = baker.make(Club, _quantity=3, is_active=True) + cls.roles = baker.make(ClubRole, _quantity=3, is_active=True) + + # Clean existing data to avoid side effects + Membership.objects.all().delete() + + cls.memberships = [ + # on going + Membership.objects.create( + club=cls.clubs[0], + user=subscriber_user.make(), + role=cls.roles[0], + start_date=date(2025, 1, 1), + end_date=None, + ), + # on going + Membership.objects.create( + club=cls.clubs[1], + user=subscriber_user.make(), + role=cls.roles[1], + start_date=date(2026, 5, 1), + end_date=None, + ), + # former + Membership.objects.create( + club=cls.clubs[1], + user=subscriber_user.make(), + role=cls.roles[2], + start_date=date(2024, 6, 1), + end_date=date(2025, 8, 1), + ), + # on going + Membership.objects.create( + club=cls.clubs[2], + user=subscriber_user.make(), + role=cls.roles[0], + start_date=date(2024, 1, 1), + end_date=None, + ), + # former + Membership.objects.create( + club=cls.clubs[1], + user=subscriber_user.make(), + role=cls.roles[2], + start_date=date(2025, 6, 1), + end_date=date(2025, 8, 1), + ), + # on going + Membership.objects.create( + club=cls.clubs[2], + user=subscriber_user.make(), + role=cls.roles[0], + start_date=date(2026, 6, 6), + end_date=None, + ), + # former + Membership.objects.create( + club=cls.clubs[0], + user=subscriber_user.make(), + role=cls.roles[0], + start_date=date(2020, 1, 1), + end_date=date(2025, 6, 8), + ), + # former + Membership.objects.create( + club=cls.clubs[2], + user=subscriber_user.make(), + role=cls.roles[0], + start_date=date(2020, 1, 1), + end_date=date(2025, 6, 8), + ), + ] + + +class TestNewMembershipAPI(TestMembershipAPI): + def test_new_membership_one_club(self): + assert self.user.has_perm("club.view_club") + self.client.force_login(self.user) + since_date = date(2025, 1, 1) + arg = {"since_date": since_date, "clubs_id": self.clubs[0].id} + url = reverse("api:get_new_clubs_members_since_date") + response = self.client.get(url, arg) + assert response.status_code == 200 + data = response.json() + + membership_ids = [e["id"] for e in data] + expected_ids = [self.memberships[0].id] + assert membership_ids == expected_ids + + def test_new_membership_multiple_club(self): + assert self.user.has_perm("club.view_club") + self.client.force_login(self.user) + since_date = date(2025, 1, 1) + arg = { + "since_date": since_date, + "clubs_id": [self.clubs[0].id, self.clubs[1].id], + } + url = reverse("api:get_new_clubs_members_since_date") + response = self.client.get(url, arg) + assert response.status_code == 200 + data = response.json() + + membership_ids = [e["id"] for e in data] + expected_ids = [self.memberships[0].id, self.memberships[1].id] + assert membership_ids == expected_ids + + def test_new_membership_all_clubs(self): + assert self.user.has_perm("club.view_club") + self.client.force_login(self.user) + since_date = date(2025, 1, 1) + arg = {"since_date": since_date} + url = reverse("api:get_new_clubs_members_since_date") + response = self.client.get(url, arg) + assert response.status_code == 200 + data = response.json() + + membership_ids = [e["id"] for e in data] + expected_ids = [ + self.memberships[0].id, + self.memberships[1].id, + self.memberships[5].id, + ] + assert membership_ids == expected_ids + + +class TestFormerMembershipAPI(TestMembershipAPI): + def test_former_membership_one_club(self): + assert self.user.has_perm("club.view_club") + self.client.force_login(self.user) + since_date = date(2025, 1, 1) + arg = {"since_date": since_date, "clubs_id": self.clubs[1].id} + url = reverse("api:get_former_clubs_members_since_date") + response = self.client.get(url, arg) + assert response.status_code == 200 + data = response.json() + + membership_ids = [e["id"] for e in data] + expected_ids = [self.memberships[2].id] + assert membership_ids == expected_ids + + def test_new_membership_multiple_club(self): + assert self.user.has_perm("club.view_club") + self.client.force_login(self.user) + since_date = date(2025, 1, 1) + arg = { + "since_date": since_date, + "clubs_id": [self.clubs[1].id, self.clubs[0].id], + } + url = reverse("api:get_former_clubs_members_since_date") + response = self.client.get(url, arg) + assert response.status_code == 200 + data = response.json() + + membership_ids = [e["id"] for e in data] + expected_ids = [self.memberships[6].id, self.memberships[2].id] + assert membership_ids == expected_ids + + def test_new_membership_all_clubs(self): + assert self.user.has_perm("club.view_club") + self.client.force_login(self.user) + since_date = date(2025, 1, 1) + arg = {"since_date": since_date} + url = reverse("api:get_former_clubs_members_since_date") + response = self.client.get(url, arg) + assert response.status_code == 200 + data = response.json() + + membership_ids = [e["id"] for e in data] + expected_ids = [ + self.memberships[6].id, + self.memberships[7].id, + self.memberships[2].id, + ] + assert membership_ids == expected_ids From 648b6b6af07dee4bc133f5b94b011c67fc78c535 Mon Sep 17 00:00:00 2001 From: TitouanDor Date: Tue, 23 Jun 2026 15:30:13 +0200 Subject: [PATCH 4/6] modification des tests --- club/api.py | 12 ++-- club/tests/test_club_membership_controller.py | 72 +++++++++++-------- 2 files changed, 48 insertions(+), 36 deletions(-) diff --git a/club/api.py b/club/api.py index 8115e92b..e3f4e440 100644 --- a/club/api.py +++ b/club/api.py @@ -79,10 +79,10 @@ class ClubMembershipController(ControllerBase): memberships = Membership.objects.ongoing().filter( start_date__gte=filters.since_date, end_date__isnull=True ) - if filters.clubs_id is None: - return memberships.order_by("start_date") + if filters.clubs_id: + memberships = memberships.filter(club_id__in=filters.clubs_id) - return memberships.filter(club_id__in=filters.clubs_id) + return memberships.order_by("start_date") @route.get( "/former", @@ -97,7 +97,7 @@ class ClubMembershipController(ControllerBase): start_date__lt=filters.since_date, end_date__gte=filters.since_date, ) - if filters.clubs_id is None: - return memberships.order_by("start_date") + if filters.clubs_id: + memberships = memberships.filter(club_id__in=filters.clubs_id) - return memberships.filter(club_id__in=filters.clubs_id) + return memberships.order_by("start_date") diff --git a/club/tests/test_club_membership_controller.py b/club/tests/test_club_membership_controller.py index 73268634..406494b7 100644 --- a/club/tests/test_club_membership_controller.py +++ b/club/tests/test_club_membership_controller.py @@ -1,8 +1,9 @@ -from datetime import date +from datetime import timedelta from django.contrib.auth.models import Permission from django.test import TestCase from django.urls import reverse +from django.utils.timezone import localdate from model_bakery import baker from club.models import Club, ClubRole, Membership @@ -28,64 +29,68 @@ class TestMembershipAPI(TestCase): club=cls.clubs[0], user=subscriber_user.make(), role=cls.roles[0], - start_date=date(2025, 1, 1), - end_date=None, + start_date=localdate() - timedelta(weeks=1), ), # on going Membership.objects.create( club=cls.clubs[1], user=subscriber_user.make(), role=cls.roles[1], - start_date=date(2026, 5, 1), - end_date=None, + start_date=localdate() - timedelta(days=1), ), # former Membership.objects.create( club=cls.clubs[1], user=subscriber_user.make(), role=cls.roles[2], - start_date=date(2024, 6, 1), - end_date=date(2025, 8, 1), + start_date=localdate() - timedelta(weeks=2), + end_date=localdate() - timedelta(days=6), ), # on going Membership.objects.create( club=cls.clubs[2], user=subscriber_user.make(), role=cls.roles[0], - start_date=date(2024, 1, 1), - end_date=None, + start_date=localdate() - timedelta(weeks=3), ), # former Membership.objects.create( club=cls.clubs[1], user=subscriber_user.make(), role=cls.roles[2], - start_date=date(2025, 6, 1), - end_date=date(2025, 8, 1), + start_date=localdate() - timedelta(days=4), + end_date=localdate() - timedelta(days=3), ), # on going Membership.objects.create( club=cls.clubs[2], user=subscriber_user.make(), role=cls.roles[0], - start_date=date(2026, 6, 6), - end_date=None, + start_date=localdate() - timedelta(days=1), ), # former Membership.objects.create( club=cls.clubs[0], user=subscriber_user.make(), role=cls.roles[0], - start_date=date(2020, 1, 1), - end_date=date(2025, 6, 8), + start_date=localdate() - timedelta(weeks=6), + end_date=localdate() - timedelta(days=3), ), # former Membership.objects.create( club=cls.clubs[2], user=subscriber_user.make(), role=cls.roles[0], - start_date=date(2020, 1, 1), - end_date=date(2025, 6, 8), + start_date=localdate() - timedelta(weeks=8), + end_date=localdate() - timedelta(days=6), + ), + # former + Membership.objects.create( + club=cls.clubs[1], + user=subscriber_user.make(), + role=cls.roles[0], + start_date=localdate() - timedelta(weeks=8), + end_date=localdate() - timedelta(weeks=7, days=5), ), ] @@ -94,10 +99,11 @@ class TestNewMembershipAPI(TestMembershipAPI): def test_new_membership_one_club(self): assert self.user.has_perm("club.view_club") self.client.force_login(self.user) - since_date = date(2025, 1, 1) + since_date = localdate() - timedelta(weeks=1) arg = {"since_date": since_date, "clubs_id": self.clubs[0].id} url = reverse("api:get_new_clubs_members_since_date") - response = self.client.get(url, arg) + with self.assertNumQueries(8): + response = self.client.get(url, arg) assert response.status_code == 200 data = response.json() @@ -108,13 +114,14 @@ class TestNewMembershipAPI(TestMembershipAPI): def test_new_membership_multiple_club(self): assert self.user.has_perm("club.view_club") self.client.force_login(self.user) - since_date = date(2025, 1, 1) + since_date = localdate() - timedelta(weeks=1) arg = { "since_date": since_date, "clubs_id": [self.clubs[0].id, self.clubs[1].id], } url = reverse("api:get_new_clubs_members_since_date") - response = self.client.get(url, arg) + with self.assertNumQueries(11): + response = self.client.get(url, arg) assert response.status_code == 200 data = response.json() @@ -125,10 +132,11 @@ class TestNewMembershipAPI(TestMembershipAPI): def test_new_membership_all_clubs(self): assert self.user.has_perm("club.view_club") self.client.force_login(self.user) - since_date = date(2025, 1, 1) + since_date = localdate() - timedelta(weeks=1) arg = {"since_date": since_date} url = reverse("api:get_new_clubs_members_since_date") - response = self.client.get(url, arg) + with self.assertNumQueries(14): + response = self.client.get(url, arg) assert response.status_code == 200 data = response.json() @@ -145,10 +153,12 @@ class TestFormerMembershipAPI(TestMembershipAPI): def test_former_membership_one_club(self): assert self.user.has_perm("club.view_club") self.client.force_login(self.user) - since_date = date(2025, 1, 1) + since_date = localdate() - timedelta(weeks=1) arg = {"since_date": since_date, "clubs_id": self.clubs[1].id} url = reverse("api:get_former_clubs_members_since_date") - response = self.client.get(url, arg) + with self.assertNumQueries(8): + response = self.client.get(url, arg) + assert response.status_code == 200 data = response.json() @@ -159,13 +169,14 @@ class TestFormerMembershipAPI(TestMembershipAPI): def test_new_membership_multiple_club(self): assert self.user.has_perm("club.view_club") self.client.force_login(self.user) - since_date = date(2025, 1, 1) + since_date = localdate() - timedelta(weeks=1) arg = { "since_date": since_date, "clubs_id": [self.clubs[1].id, self.clubs[0].id], } url = reverse("api:get_former_clubs_members_since_date") - response = self.client.get(url, arg) + with self.assertNumQueries(11): + response = self.client.get(url, arg) assert response.status_code == 200 data = response.json() @@ -176,17 +187,18 @@ class TestFormerMembershipAPI(TestMembershipAPI): def test_new_membership_all_clubs(self): assert self.user.has_perm("club.view_club") self.client.force_login(self.user) - since_date = date(2025, 1, 1) + since_date = localdate() - timedelta(weeks=1) arg = {"since_date": since_date} url = reverse("api:get_former_clubs_members_since_date") - response = self.client.get(url, arg) + with self.assertNumQueries(14): + response = self.client.get(url, arg) assert response.status_code == 200 data = response.json() membership_ids = [e["id"] for e in data] expected_ids = [ - self.memberships[6].id, self.memberships[7].id, + self.memberships[6].id, self.memberships[2].id, ] assert membership_ids == expected_ids From 5625268d6b2ae775cb9eef5d17c371585dd398bf Mon Sep 17 00:00:00 2001 From: TitouanDor Date: Tue, 23 Jun 2026 22:13:55 +0200 Subject: [PATCH 5/6] =?UTF-8?q?ajout=20modif=20demand=C3=A9es?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- club/api.py | 8 ++-- club/tests/test_club_membership_controller.py | 46 +++++++++---------- 2 files changed, 27 insertions(+), 27 deletions(-) diff --git a/club/api.py b/club/api.py index e3f4e440..150bf487 100644 --- a/club/api.py +++ b/club/api.py @@ -76,8 +76,10 @@ class ClubMembershipController(ControllerBase): ) def fetch_new_club_members(self, filters: Query[MembershipFilterSchema]): """give all the members of all clubs that have joined since a given date""" - memberships = Membership.objects.ongoing().filter( - start_date__gte=filters.since_date, end_date__isnull=True + memberships = ( + Membership.objects.ongoing() + .filter(start_date__gte=filters.since_date, end_date__isnull=True) + .select_related("user", "role") ) if filters.clubs_id: memberships = memberships.filter(club_id__in=filters.clubs_id) @@ -96,7 +98,7 @@ class ClubMembershipController(ControllerBase): memberships = Membership.objects.filter( start_date__lt=filters.since_date, end_date__gte=filters.since_date, - ) + ).select_related("user", "role") if filters.clubs_id: memberships = memberships.filter(club_id__in=filters.clubs_id) diff --git a/club/tests/test_club_membership_controller.py b/club/tests/test_club_membership_controller.py index 406494b7..82e1afa0 100644 --- a/club/tests/test_club_membership_controller.py +++ b/club/tests/test_club_membership_controller.py @@ -96,14 +96,17 @@ class TestMembershipAPI(TestCase): class TestNewMembershipAPI(TestMembershipAPI): + @classmethod + def setUpTestData(cls): + super().setUpTestData() + cls.url = reverse("api:get_new_clubs_members_since_date") + def test_new_membership_one_club(self): - assert self.user.has_perm("club.view_club") self.client.force_login(self.user) since_date = localdate() - timedelta(weeks=1) arg = {"since_date": since_date, "clubs_id": self.clubs[0].id} - url = reverse("api:get_new_clubs_members_since_date") - with self.assertNumQueries(8): - response = self.client.get(url, arg) + with self.assertNumQueries(6): + response = self.client.get(self.url, query_params=arg) assert response.status_code == 200 data = response.json() @@ -112,16 +115,14 @@ class TestNewMembershipAPI(TestMembershipAPI): assert membership_ids == expected_ids def test_new_membership_multiple_club(self): - assert self.user.has_perm("club.view_club") self.client.force_login(self.user) since_date = localdate() - timedelta(weeks=1) arg = { "since_date": since_date, "clubs_id": [self.clubs[0].id, self.clubs[1].id], } - url = reverse("api:get_new_clubs_members_since_date") - with self.assertNumQueries(11): - response = self.client.get(url, arg) + with self.assertNumQueries(7): + response = self.client.get(self.url, query_params=arg) assert response.status_code == 200 data = response.json() @@ -130,13 +131,11 @@ class TestNewMembershipAPI(TestMembershipAPI): assert membership_ids == expected_ids def test_new_membership_all_clubs(self): - assert self.user.has_perm("club.view_club") self.client.force_login(self.user) since_date = localdate() - timedelta(weeks=1) arg = {"since_date": since_date} - url = reverse("api:get_new_clubs_members_since_date") - with self.assertNumQueries(14): - response = self.client.get(url, arg) + with self.assertNumQueries(8): + response = self.client.get(self.url, query_params=arg) assert response.status_code == 200 data = response.json() @@ -150,14 +149,17 @@ class TestNewMembershipAPI(TestMembershipAPI): class TestFormerMembershipAPI(TestMembershipAPI): + @classmethod + def setUpTestData(cls): + super().setUpTestData() + cls.url = reverse("api:get_former_clubs_members_since_date") + def test_former_membership_one_club(self): - assert self.user.has_perm("club.view_club") self.client.force_login(self.user) since_date = localdate() - timedelta(weeks=1) arg = {"since_date": since_date, "clubs_id": self.clubs[1].id} - url = reverse("api:get_former_clubs_members_since_date") - with self.assertNumQueries(8): - response = self.client.get(url, arg) + with self.assertNumQueries(6): + response = self.client.get(self.url, query_params=arg) assert response.status_code == 200 data = response.json() @@ -167,16 +169,14 @@ class TestFormerMembershipAPI(TestMembershipAPI): assert membership_ids == expected_ids def test_new_membership_multiple_club(self): - assert self.user.has_perm("club.view_club") self.client.force_login(self.user) since_date = localdate() - timedelta(weeks=1) arg = { "since_date": since_date, "clubs_id": [self.clubs[1].id, self.clubs[0].id], } - url = reverse("api:get_former_clubs_members_since_date") - with self.assertNumQueries(11): - response = self.client.get(url, arg) + with self.assertNumQueries(7): + response = self.client.get(self.url, query_params=arg) assert response.status_code == 200 data = response.json() @@ -185,13 +185,11 @@ class TestFormerMembershipAPI(TestMembershipAPI): assert membership_ids == expected_ids def test_new_membership_all_clubs(self): - assert self.user.has_perm("club.view_club") self.client.force_login(self.user) since_date = localdate() - timedelta(weeks=1) arg = {"since_date": since_date} - url = reverse("api:get_former_clubs_members_since_date") - with self.assertNumQueries(14): - response = self.client.get(url, arg) + with self.assertNumQueries(8): + response = self.client.get(self.url, query_params=arg) assert response.status_code == 200 data = response.json() From dcdfb086edb022b5ec0790a1a902fd5332d6600f Mon Sep 17 00:00:00 2001 From: TitouanDor Date: Tue, 23 Jun 2026 22:56:51 +0200 Subject: [PATCH 6/6] ajout club dans select_related() --- club/api.py | 4 ++-- club/tests/test_club_membership_controller.py | 13 +++++++------ 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/club/api.py b/club/api.py index 150bf487..cf1070d0 100644 --- a/club/api.py +++ b/club/api.py @@ -79,7 +79,7 @@ class ClubMembershipController(ControllerBase): memberships = ( Membership.objects.ongoing() .filter(start_date__gte=filters.since_date, end_date__isnull=True) - .select_related("user", "role") + .select_related("user", "role", "club") ) if filters.clubs_id: memberships = memberships.filter(club_id__in=filters.clubs_id) @@ -98,7 +98,7 @@ class ClubMembershipController(ControllerBase): memberships = Membership.objects.filter( start_date__lt=filters.since_date, end_date__gte=filters.since_date, - ).select_related("user", "role") + ).select_related("user", "role", "club") if filters.clubs_id: memberships = memberships.filter(club_id__in=filters.clubs_id) diff --git a/club/tests/test_club_membership_controller.py b/club/tests/test_club_membership_controller.py index 82e1afa0..27aee901 100644 --- a/club/tests/test_club_membership_controller.py +++ b/club/tests/test_club_membership_controller.py @@ -19,6 +19,7 @@ class TestMembershipAPI(TestCase): cls.user.user_permissions.add(perm) cls.clubs = baker.make(Club, _quantity=3, is_active=True) cls.roles = baker.make(ClubRole, _quantity=3, is_active=True) + cls.expectedNumQueries = 5 # Clean existing data to avoid side effects Membership.objects.all().delete() @@ -105,7 +106,7 @@ class TestNewMembershipAPI(TestMembershipAPI): self.client.force_login(self.user) since_date = localdate() - timedelta(weeks=1) arg = {"since_date": since_date, "clubs_id": self.clubs[0].id} - with self.assertNumQueries(6): + with self.assertNumQueries(self.expectedNumQueries): response = self.client.get(self.url, query_params=arg) assert response.status_code == 200 data = response.json() @@ -121,7 +122,7 @@ class TestNewMembershipAPI(TestMembershipAPI): "since_date": since_date, "clubs_id": [self.clubs[0].id, self.clubs[1].id], } - with self.assertNumQueries(7): + with self.assertNumQueries(self.expectedNumQueries): response = self.client.get(self.url, query_params=arg) assert response.status_code == 200 data = response.json() @@ -134,7 +135,7 @@ class TestNewMembershipAPI(TestMembershipAPI): self.client.force_login(self.user) since_date = localdate() - timedelta(weeks=1) arg = {"since_date": since_date} - with self.assertNumQueries(8): + with self.assertNumQueries(self.expectedNumQueries): response = self.client.get(self.url, query_params=arg) assert response.status_code == 200 data = response.json() @@ -158,7 +159,7 @@ class TestFormerMembershipAPI(TestMembershipAPI): self.client.force_login(self.user) since_date = localdate() - timedelta(weeks=1) arg = {"since_date": since_date, "clubs_id": self.clubs[1].id} - with self.assertNumQueries(6): + with self.assertNumQueries(self.expectedNumQueries): response = self.client.get(self.url, query_params=arg) assert response.status_code == 200 @@ -175,7 +176,7 @@ class TestFormerMembershipAPI(TestMembershipAPI): "since_date": since_date, "clubs_id": [self.clubs[1].id, self.clubs[0].id], } - with self.assertNumQueries(7): + with self.assertNumQueries(self.expectedNumQueries): response = self.client.get(self.url, query_params=arg) assert response.status_code == 200 data = response.json() @@ -188,7 +189,7 @@ class TestFormerMembershipAPI(TestMembershipAPI): self.client.force_login(self.user) since_date = localdate() - timedelta(weeks=1) arg = {"since_date": since_date} - with self.assertNumQueries(8): + with self.assertNumQueries(self.expectedNumQueries): response = self.client.get(self.url, query_params=arg) assert response.status_code == 200 data = response.json()