Skip to content

Commit 73b070d

Browse files
committed
add patron list api
1 parent 8ee8cc7 commit 73b070d

File tree

4 files changed

+111
-7
lines changed

4 files changed

+111
-7
lines changed

sponsor/serializers.py

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import rest_framework.serializers as serializers
22
from rest_framework.fields import SerializerMethodField
33

4-
from sponsor.models import Sponsor, SponsorLevel
4+
from sponsor.models import Patron, Sponsor, SponsorLevel
55

66

77
class SponsorSerializer(serializers.ModelSerializer):
@@ -74,3 +74,23 @@ def get_remaining(obj):
7474
@staticmethod
7575
def get_available(obj: SponsorLevel):
7676
return True if obj.current_remaining_number > 0 else False
77+
78+
79+
class PatronListSerializer(serializers.ModelSerializer):
80+
class Meta:
81+
model = Patron
82+
fields = [
83+
"name",
84+
"contribution_message",
85+
"sort_order",
86+
]
87+
88+
sort_order = serializers.SerializerMethodField()
89+
90+
def get_sort_order(self, obj: Patron):
91+
self._sort_order += 1
92+
return self._sort_order
93+
94+
def __init__(self, *args, **kwargs):
95+
super().__init__(*args, **kwargs)
96+
self._sort_order = 0

sponsor/tests.py

Lines changed: 72 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,17 @@
11
import pytest
22
from django.contrib.auth import get_user_model
3+
from rest_framework.test import APIClient
34

4-
from sponsor.models import SponsorLevel
5+
from sponsor.models import Patron, SponsorLevel
56

67
pytestmark = pytest.mark.django_db
78

89
UserModel = get_user_model()
910

1011

12+
client = APIClient()
13+
14+
1115
@pytest.mark.django_db
1216
class TestSponsorLevelModel:
1317
pytestmark = pytest.mark.django_db
@@ -23,4 +27,70 @@ def test_sponsor_level_creation_success(self):
2327
assert SponsorLevel.objects.count() != 0
2428

2529

26-
# Create your tests here.
30+
@pytest.mark.django_db
31+
class TestPatron:
32+
pytestmark = pytest.mark.django_db
33+
34+
def test_patron_list_api(self):
35+
assert Patron.objects.count() == 0
36+
response = client.get("/sponsors/patron/list/", format="json")
37+
assert response.status_code == 200
38+
assert len(response.data) == 0
39+
40+
Patron.objects.create(
41+
name="Python Lover 1",
42+
contribution_message="I love Python",
43+
total_contribution=1000000,
44+
contribution_datetime="2023-07-27 00:00:00+09:00",
45+
)
46+
assert Patron.objects.count() == 1
47+
response = client.get("/sponsors/patron/list/", format="json")
48+
assert response.status_code == 200
49+
assert len(response.data) == 1
50+
assert response.data[0]["name"] == "Python Lover 1"
51+
# check sort order
52+
assert response.data[0]["sort_order"] == 1
53+
54+
# add second patron
55+
Patron.objects.create(
56+
name="Python Lover 2",
57+
contribution_message="I love Python too",
58+
total_contribution=1000001,
59+
contribution_datetime="2023-07-27 00:00:00+09:00",
60+
)
61+
assert Patron.objects.count() == 2
62+
response = client.get("/sponsors/patron/list/", format="json")
63+
assert response.status_code == 200
64+
assert len(response.data) == 2
65+
assert response.data[0]["name"] == "Python Lover 2"
66+
# check sort order
67+
assert response.data[0]["sort_order"] == 1
68+
assert response.data[1]["name"] == "Python Lover 1"
69+
assert response.data[1]["sort_order"] == 2
70+
71+
# add third patron
72+
# check contribution_datetime is earlier than Python Lover 2
73+
Patron.objects.create(
74+
name="Python Lover 3",
75+
contribution_message="I love Python most",
76+
total_contribution=1000001,
77+
# earlier contribution then Python Lover 2
78+
contribution_datetime="2023-07-26 00:00:00+09:00",
79+
)
80+
assert Patron.objects.count() == 3
81+
response = client.get("/sponsors/patron/list/", format="json")
82+
assert response.status_code == 200
83+
assert len(response.data) == 3
84+
assert response.data[0]["name"] == "Python Lover 3"
85+
# check sort order
86+
assert response.data[0]["sort_order"] == 1
87+
assert response.data[1]["name"] == "Python Lover 2"
88+
assert response.data[1]["sort_order"] == 2
89+
90+
@pytest.skip("TODO: implement")
91+
def test_patron_message_html_sanitizer(self):
92+
assert Patron.objects.count() == 0
93+
# check patron save will sanitize html field
94+
# allow only <a> tag
95+
# allow emoji
96+
pass

sponsor/urls.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
11
from django.urls import path
22

3-
from sponsor.viewsets import SponsorViewSet
3+
from sponsor.viewsets import PatronListViewSet, SponsorViewSet
44

55
urlpatterns = [
66
path("list/", SponsorViewSet.as_view({"get": "list"})),
77
path(
88
"list/<int:id>/",
99
SponsorViewSet.as_view({"get": "retrieve", "put": "update"}),
1010
),
11+
path(
12+
"patron/list/",
13+
PatronListViewSet.as_view({"get": "list"}),
14+
),
1115
]

sponsor/viewsets.py

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,12 @@
44
from django.shortcuts import get_object_or_404
55
from rest_framework import status
66
from rest_framework.response import Response
7-
from rest_framework.viewsets import ModelViewSet
7+
from rest_framework.viewsets import ModelViewSet, ViewSet
88

9-
from sponsor.models import Sponsor, SponsorLevel
9+
from sponsor.models import Patron, Sponsor, SponsorLevel
1010
from sponsor.permissions import IsOwnerOrReadOnly, OwnerOnly
1111
from sponsor.serializers import (
12+
PatronListSerializer,
1213
SponsorDetailSerializer,
1314
SponsorListSerializer,
1415
SponsorRemainingAccountSerializer,
@@ -28,7 +29,9 @@ def get_queryset(self):
2829
return Sponsor.objects.all().order_by("paid_at")
2930

3031
def list(self, request, *args, **kwargs):
31-
queryset = Sponsor.objects.filter(paid_at__isnull=False).order_by("level", "paid_at")
32+
queryset = Sponsor.objects.filter(paid_at__isnull=False).order_by(
33+
"level", "paid_at"
34+
)
3235
serializer = SponsorListSerializer(queryset, many=True)
3336
return Response(serializer.data)
3437

@@ -109,3 +112,10 @@ def list(self, request, *args, **kwargs):
109112
serializer = self.get_serializer(queryset, many=True)
110113

111114
return Response(serializer.data)
115+
116+
117+
class PatronListViewSet(ViewSet):
118+
def list(self, request):
119+
queryset = Patron.objects.all()
120+
serializer = PatronListSerializer(queryset, many=True)
121+
return Response(serializer.data)

0 commit comments

Comments
 (0)