Skip to content

Commit b4f58d4

Browse files
committed
The changes made in this commit include:
- Added `src/base/serializers.py` - Modified `src/signal_documentation/settings.py` to remove a line - Modified `src/signals/filters.py` to add a class docstring and a method docstring - Modified `src/signals/resources.py` to add class docstrings and method docstrings - Added `src/signals/serializers.py` - Modified `src/signals/urls.py` to add a new API endpoint - Modified `src/signals/views.py` to add class docstrings and a new API view
1 parent 0bf9434 commit b4f58d4

File tree

7 files changed

+141
-9
lines changed

7 files changed

+141
-9
lines changed

src/base/serializers.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
from rest_framework.serializers import ModelSerializer
2+
3+
from base.models import Link
4+
5+
6+
class LinkSerializer(ModelSerializer):
7+
"""
8+
Serializer for the Link model.
9+
"""
10+
class Meta:
11+
model = Link
12+
fields = ['link_type', 'url']

src/signal_documentation/settings.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,6 @@
177177
'DEFAULT_FILTER_BACKENDS': (
178178
'django_filters.rest_framework.DjangoFilterBackend',
179179
),
180-
181180
}
182181

183182

src/signals/filters.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@
88

99

1010
class SignalFilter(django_filters.FilterSet):
11+
"""
12+
FilterSet for the Signal model.
13+
"""
14+
1115
search = CharFilter(method='filter_search')
1216

1317
class Meta:
@@ -24,6 +28,18 @@ class Meta:
2428
]
2529

2630
def filter_search(self, queryset, name, value) -> Any:
31+
"""
32+
Custom filter method to perform a search on the Signal model.
33+
34+
Args:
35+
queryset (QuerySet): The initial queryset.
36+
name (str): The name of the filter field.
37+
value (Any): The value to search for.
38+
39+
Returns:
40+
QuerySet: The filtered queryset based on the search value.
41+
"""
42+
2743
if not value:
2844
return queryset
2945

src/signals/resources.py

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@
1717

1818

1919
class SignalBaseResource(resources.ModelResource):
20+
"""
21+
Resource class for importing Signals base.
22+
"""
23+
2024
name = Field(attribute='name', column_name='Signal')
2125
display_name = Field(attribute='display_name', column_name='Name')
2226
base = Field(
@@ -49,7 +53,9 @@ def process_base(self, row) -> None:
4953

5054

5155
class SignalResource(resources.ModelResource):
52-
"""Resource class for importing and exporting Signal models."""
56+
"""
57+
Resource class for importing and exporting Signal models
58+
"""
5359

5460
name = Field(attribute='name', column_name='Signal')
5561
display_name = Field(attribute='display_name', column_name='Name')
@@ -122,19 +128,26 @@ class Meta:
122128
import_id_fields: list[str] = ['name', 'source', 'display_name']
123129

124130
def before_import_row(self, row, **kwargs) -> None:
125-
"""Pre-processes each row before importing."""
131+
"""
132+
Pre-processes each row before importing.
133+
"""
134+
126135
self.fix_boolean_fields(row, ['Active', 'Is Smoothed', 'Is Weighted', 'Is Cumulative', 'Has StdErr', 'Has Sample Size'])
127136
self.process_links(row)
128137
self.process_pathogen(row)
129138

130139
def is_url_in_domain(self, url, domain) -> Any:
131-
"""Checks if a URL belongs to a specific domain."""
140+
"""
141+
Checks if a URL belongs to a specific domain.
142+
"""
132143

133144
parsed_url: Any = urlparse(url)
134145
return parsed_url.netloc == domain
135146

136147
def fix_boolean_fields(self, row, fields: list) -> Any:
137-
"""Fixes boolean fields."""
148+
"""
149+
Fixes boolean fields.
150+
"""
138151

139152
for k in fields:
140153
if row[k] == 'TRUE':
@@ -144,7 +157,9 @@ def fix_boolean_fields(self, row, fields: list) -> Any:
144157
return row
145158

146159
def process_links(self, row) -> Any:
147-
"""Processes links."""
160+
"""
161+
Processes links.
162+
"""
148163

149164
row['Links'] = ''
150165
if row['Link']:
@@ -170,7 +185,9 @@ def process_links(self, row) -> Any:
170185
return row
171186

172187
def process_pathogen(self, row) -> None:
173-
"""Processes pathogen."""
188+
"""
189+
Processes pathogen.
190+
"""
174191

175192
if row['Pathogen/ Disease Area']:
176193
pathogens: str = row['Pathogen/ Disease Area'].split(',')

src/signals/serializers.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
from rest_framework.serializers import ModelSerializer, SlugRelatedField
2+
3+
from base.serializers import LinkSerializer
4+
from signals.models import Signal
5+
6+
7+
class SignalBaseSerializer(ModelSerializer):
8+
"""
9+
Serializer for the base Signal model.
10+
"""
11+
12+
class Meta:
13+
model = Signal
14+
fields = ['id', 'name', 'display_name']
15+
16+
17+
class SignalSerializer(ModelSerializer):
18+
"""
19+
Serializer for the Signal model.
20+
"""
21+
22+
links = LinkSerializer(many=True)
23+
pathogen = SlugRelatedField(many=True, read_only=True, slug_field='name')
24+
signal_type = SlugRelatedField(many=True, read_only=True, slug_field='name')
25+
available_geography = SlugRelatedField(many=True, read_only=True, slug_field='name')
26+
category = SlugRelatedField(read_only=True, slug_field='name')
27+
source = SlugRelatedField(read_only=True, slug_field='name')
28+
base = SignalBaseSerializer()
29+
30+
class Meta:
31+
model = Signal
32+
fields = '__all__'

src/signals/urls.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,17 @@
11
from django.urls import path
22
from django.urls.resolvers import URLPattern
33

4-
from signals.views import SignalsDetailView, SignalsListView
4+
from signals.views import (
5+
SignalsDetailView,
6+
SignalsListApiView,
7+
SignalsListView,
8+
)
59

610
urlpatterns: list[URLPattern] = [
711
path('', SignalsListView.as_view(), name='signals'),
812
path('signals/<pk>/', SignalsDetailView.as_view(), name='signal'),
13+
14+
# REST API
15+
path('api/v1/signals/', SignalsListApiView.as_view(), name='signals_api'),
16+
917
]

src/signals/views.py

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,48 @@
11
from typing import Any, Dict
22

3+
from django.conf import settings
34
from django.core.paginator import Page, Paginator
45
from django.utils.decorators import method_decorator
56
from django.views.decorators.cache import cache_page
67
from django.views.generic import DetailView, ListView
8+
from django_filters.rest_framework import DjangoFilterBackend
9+
from rest_framework.filters import SearchFilter
10+
from rest_framework.generics import ListAPIView
711

812
from signals.filters import SignalFilter
913
from signals.models import Signal
14+
from signals.serializers import SignalSerializer
1015

1116

1217
class SignalsListView(ListView):
18+
"""
19+
ListView for displaying a list of Signal objects.
20+
"""
1321

1422
model = Signal
1523
template_name = 'signals/signal_list.html'
16-
paginate_by = 10
24+
paginate_by = settings.PAGE_SIZE
1725

1826
def get_queryset(self) -> Any:
27+
"""
28+
Get the queryset for the view.
29+
30+
Returns:
31+
QuerySet: The queryset for the view.
32+
"""
33+
1934
queryset = super().get_queryset()
2035
f = SignalFilter(self.request.GET, queryset=queryset)
2136
return f.qs
2237

2338
def get_context_data(self, **kwargs) -> Dict[str, Any]:
39+
"""
40+
Get the context data for the view.
41+
42+
Returns:
43+
Dict[str, Any]: The context data for the view.
44+
"""
45+
2446
context: Dict[str, Any] = super().get_context_data(**kwargs)
2547
context['filter'] = SignalFilter(self.request.GET, queryset=self.get_queryset())
2648
paginator = Paginator(self.get_queryset(), self.paginate_by)
@@ -32,5 +54,31 @@ def get_context_data(self, **kwargs) -> Dict[str, Any]:
3254

3355
@method_decorator(cache_page(60 * 5), name='dispatch')
3456
class SignalsDetailView(DetailView):
57+
"""
58+
DetailView for displaying a single Signal object.
59+
"""
3560

3661
model = Signal
62+
63+
64+
class SignalsListApiView(ListAPIView):
65+
"""
66+
ListAPIView for retrieving a list of Signal objects via API.
67+
"""
68+
69+
queryset = Signal.objects.all()
70+
serializer_class = SignalSerializer
71+
search_fields = ('name', 'display_name', 'description', 'short_description')
72+
filter_backends = [SearchFilter, DjangoFilterBackend]
73+
filterset_fields = (
74+
'name',
75+
'display_name',
76+
'pathogen__name',
77+
'available_geography__name',
78+
'signal_type__name',
79+
'category__name',
80+
'format',
81+
'base',
82+
'source__name',
83+
'time_label',
84+
)

0 commit comments

Comments
 (0)