Skip to content

Commit 20985c2

Browse files
Merge pull request #2032 from IFRCGo/feature/add-filters-to-opslearning
Add filters to opslearning
2 parents e1361af + d7a9f72 commit 20985c2

File tree

5 files changed

+67
-77
lines changed

5 files changed

+67
-77
lines changed

main/urls.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,15 +59,15 @@
5959
from databank.views import CountryOverviewViewSet
6060
from local_units.views import (
6161
LocalUnitListAPIView, LocalUnitDetailAPIView,
62-
DelegationOfficeListAPIView, DelegationOfficeDetailAPIView
63-
)
62+
DelegationOfficeListAPIView, DelegationOfficeDetailAPIView)
6463

6564
# DRF routes
6665
from rest_framework import routers
6766
from drf_spectacular.views import SpectacularAPIView, SpectacularRedocView, SpectacularSwaggerView
6867
from api import drf_views as api_views
6968
from flash_update import views as flash_views
7069
from per import drf_views as per_views
70+
from per.views import LearningTypes
7171
from deployments import drf_views as deployment_views
7272
from notifications import drf_views as notification_views
7373
from registrations import drf_views as registration_views
@@ -189,6 +189,7 @@
189189
url(r"^api/v2/primarysector", ProjectPrimarySectors.as_view()),
190190
url(r"^api/v2/secondarysector", ProjectSecondarySectors.as_view()),
191191
url(r"^api/v2/projectstatus", ProjectStatuses.as_view()),
192+
url(r"^api/v2/learningtype", LearningTypes.as_view()),
192193
# url(r"^api/v2/create_field_report/", api_views.CreateFieldReport.as_view()),
193194
# url(r"^api/v2/update_field_report/(?P<pk>\d+)/", api_views.UpdateFieldReport.as_view()),
194195
url(r"^get_auth_token", GetAuthToken.as_view()),

notifications/tests.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import typing
21
from datetime import datetime, timezone
32
from django.conf import settings
43
from modeltranslation.utils import build_localized_fieldname

per/drf_views.py

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,14 @@
1919

2020
from .admin_classes import RegionRestrictedAdmin
2121
from api.models import Country
22+
from deployments.models import SectorTag
2223
from .models import (
2324
FormData,
2425
FormArea,
2526
FormComponent,
2627
FormQuestion,
2728
FormAnswer,
29+
OrganizationTypes,
2830
OpsLearning,
2931
Overview,
3032
NiceDocument,
@@ -67,6 +69,7 @@
6769
PerPrioritizationFilter,
6870
PerWorkPlanFilter,
6971
)
72+
from django_filters.widgets import CSVWidget
7073
from .custom_renderers import NarrowCSVRenderer
7174

7275

@@ -370,12 +373,64 @@ def get_queryset(self):
370373
return self.get_filtered_queryset(self.request, queryset, dispatch=0)
371374

372375

376+
class OpsLearningFilter(filters.FilterSet):
377+
type_validated = filters.NumberFilter(field_name='type_validated', lookup_expr='exact')
378+
appeal_document_id = filters.NumberFilter(field_name='appeal_document_id', lookup_expr='exact')
379+
organization_validated__in = filters.ModelMultipleChoiceFilter(
380+
label='validated_organizations',
381+
field_name='organization_validated',
382+
help_text='Organization GO identifiers, comma separated',
383+
widget=CSVWidget,
384+
queryset=OrganizationTypes.objects.all(),
385+
)
386+
sector_validated__in = filters.ModelMultipleChoiceFilter(
387+
label='validated_sectors',
388+
field_name='sector_validated',
389+
help_text='Sector identifiers, comma separated',
390+
widget=CSVWidget,
391+
queryset=SectorTag.objects.all(),
392+
)
393+
per_component_validated__in = filters.ModelMultipleChoiceFilter(
394+
label='validated_per_components',
395+
field_name='per_component_validated',
396+
help_text='PER Component identifiers, comma separated',
397+
widget=CSVWidget,
398+
queryset=FormComponent.objects.all(),
399+
)
400+
401+
class Meta:
402+
model = OpsLearning
403+
fields = {
404+
'id': ('exact', 'in'),
405+
'created_at': ('exact', 'gt', 'gte', 'lt', 'lte'),
406+
'modified_at': ('exact', 'gt', 'gte', 'lt', 'lte'),
407+
'is_validated': ('exact',),
408+
'learning': ('exact', 'icontains'),
409+
'learning_validated': ('exact', 'icontains'),
410+
'organization_validated': ('exact',),
411+
'sector_validated': ('exact',),
412+
'per_component_validated': ('exact',),
413+
'appeal_code': ('exact', 'in'),
414+
'appeal_code__code': ('exact', 'icontains', 'in'),
415+
'appeal_code__num_beneficiaries': ('exact', 'gt', 'gte', 'lt', 'lte'),
416+
'appeal_code__start_date': ('exact', 'gt', 'gte', 'lt', 'lte'),
417+
'appeal_code__dtype': ('exact', 'in'),
418+
'appeal_code__country': ('exact', 'in'),
419+
'appeal_code__country__name': ('exact', 'in'),
420+
'appeal_code__country__iso': ('exact', 'in'),
421+
'appeal_code__country__iso3': ('exact', 'in'),
422+
'appeal_code__region': ('exact', 'in'),
423+
}
424+
425+
373426
class OpsLearningViewset(viewsets.ModelViewSet):
374427
"""
375428
A simple ViewSet for viewing and editing OpsLearning records.
376429
"""
377430
queryset = OpsLearning.objects.all()
378431
permission_classes = [OpsLearningPermission]
432+
filterset_class = OpsLearningFilter
433+
search_fields = ('learning', 'learning_validated', 'appeal_code__code', 'appeal_code__name', 'appeal_code__name_en', 'appeal_code__name_es', 'appeal_code__name_fr', 'appeal_code__name_ar')
379434

380435
def get_renderers(self):
381436
serializer = self.get_serializer()

per/models.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -624,7 +624,7 @@ class LearningType(models.IntegerChoices):
624624
CHALLENGE = 2, _('Challenge')
625625

626626

627-
reversion.register(follow=('appeal_code', 'organization', 'sector', 'per_component', 'organization_validated', 'sector_validated', 'per_component_validated'))
627+
@reversion.register(follow=('appeal_code', 'organization', 'sector', 'per_component', 'organization_validated', 'sector_validated', 'per_component_validated'))
628628
class OpsLearning(models.Model):
629629
learning = models.TextField(verbose_name=_("learning"), null=True, blank=True)
630630
learning_validated = models.TextField(verbose_name=_("learning (validated)"), null=True, blank=True)

per/views.py

Lines changed: 8 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -6,23 +6,14 @@
66

77
from rest_framework import authentication, permissions
88
from rest_framework.views import APIView
9-
from rest_framework import (
10-
views,
11-
viewsets,
12-
response,
13-
permissions,
14-
status,
15-
mixins,
16-
serializers,
17-
)
18-
199
from .models import (
2010
Form,
2111
FormData,
2212
WorkPlan,
2313
Overview,
2414
FormArea,
2515
FormQuestion,
16+
LearningType
2617
)
2718
from .admin_classes import RegionRestrictedAdmin
2819
from api.views import bad_request
@@ -40,48 +31,6 @@ def parse_date(date_string):
4031
return datetime.strptime(date_string[:10], dateformat).replace(tzinfo=timezone.utc)
4132

4233

43-
# class CreatePerForm(APIView):
44-
# authentication_classes = (authentication.TokenAuthentication,)
45-
# permissions_classes = (permissions.IsAuthenticated,)
46-
47-
# def post(self, request):
48-
# area_id = request.data.get('area_id', None)
49-
# comment = request.data.get('comment', None)
50-
# overview_id = request.data.get('overview_id', None)
51-
# questions = request.data.get('questions', None)
52-
# user_id = request.data.get('user_id', None)
53-
54-
# if questions is None:
55-
# return bad_request('Questions are missing from the request.')
56-
57-
# try:
58-
# form = Form.objects.create(
59-
# area_id=area_id,
60-
# user_id=user_id,
61-
# comment=comment,
62-
# overview_id=overview_id
63-
# )
64-
# except Exception:
65-
# logger.error('Could not insert PER form record.', exc_info=True)
66-
# return bad_request('Could not insert PER form record.')
67-
68-
# # Create FormData of the Form
69-
# try:
70-
# with transaction.atomic(): # all or nothing
71-
# for qid in questions:
72-
# FormData.objects.create(
73-
# form=form,
74-
# question_id=qid,
75-
# selected_answer_id=questions[qid]['selected_answer'],
76-
# notes=questions[qid]['notes']
77-
# )
78-
# except Exception:
79-
# logger.error('Could not insert PER formdata record.', exc_info=True)
80-
# return bad_request('Could not insert PER formdata record.')
81-
82-
# return JsonResponse({'status': 'ok'})
83-
84-
8534
class UpdatePerForm(APIView):
8635
authentication_classes = (authentication.TokenAuthentication,)
8736
permissions_classes = (permissions.IsAuthenticated,)
@@ -234,27 +183,6 @@ def post(self, request):
234183
return JsonResponse({"status": "ok"})
235184

236185

237-
# # For now, a Form can only be deleted if it's parent Overview is deleted
238-
# class DeletePerForm(APIView):
239-
# authentication_classes = (authentication.TokenAuthentication,)
240-
# permissions_classes = (permissions.IsAuthenticated,)
241-
242-
# def post(self, request):
243-
# user = request.user
244-
# form_id = request.data.get('id', None)
245-
# if form_id is None:
246-
# return bad_request('Need to provide Form ID.')
247-
248-
# try:
249-
# # Also deletes FormData since CASCADE fk
250-
# # TODO: check for is_finalized of Overview maybe?
251-
# Form.objects.filter(id=form_id, user=user).delete()
252-
# except Exception:
253-
# return bad_request('Could not delete PER Form.')
254-
255-
# return JsonResponse({'status': 'ok'})
256-
257-
258186
class WorkPlanSent(APIView):
259187
authentication_classes = (authentication.TokenAuthentication,)
260188
permissions_classes = (permissions.IsAuthenticated,)
@@ -536,3 +464,10 @@ def post(self, request):
536464
return bad_request("Could not delete PER WorkPlan.")
537465

538466
return JsonResponse({"status": "ok"})
467+
468+
469+
class LearningTypes(APIView):
470+
@classmethod
471+
def get(cls, request):
472+
keys_labels = [{"key": i, "label": v} for i, v in LearningType.choices]
473+
return JsonResponse(keys_labels, safe=False)

0 commit comments

Comments
 (0)