Skip to content

Commit ae7ca45

Browse files
Merge pull request #1829 from IFRCGo/feat/openapi
Add openapi endpoint
2 parents 0ff17e6 + 7dc4dd1 commit ae7ca45

File tree

9 files changed

+533
-301
lines changed

9 files changed

+533
-301
lines changed

deployments/serializers.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@
4747
)
4848

4949

50-
class MiniUserSerializer(ModelSerializer):
50+
class DeploymentMiniUserSerializer(ModelSerializer):
5151
class Meta:
5252
model = User
5353
fields = (
@@ -365,7 +365,7 @@ class ProjectSerializer(ModelSerializer):
365365
status_display = serializers.CharField(source='get_status_display', read_only=True)
366366
visibility_display = serializers.CharField(source='get_visibility_display', read_only=True)
367367
annual_split_detail = AnnualSplitSerializer(source='annual_splits', many=True, read_only=True)
368-
modified_by_detail = MiniUserSerializer(source='modified_by', read_only=True)
368+
modified_by_detail = DeploymentMiniUserSerializer(source='modified_by', read_only=True)
369369

370370
@staticmethod
371371
def get_secondary_sectors_display(obj):
@@ -553,8 +553,8 @@ class EmergencyProjectSerializer(
553553
NestedCreateMixin,
554554
ModelSerializer,
555555
):
556-
created_by_details = MiniUserSerializer(source='created_by', read_only=True)
557-
modified_by_details = MiniUserSerializer(source='modified_by', read_only=True)
556+
created_by_details = DeploymentMiniUserSerializer(source='created_by', read_only=True)
557+
modified_by_details = DeploymentMiniUserSerializer(source='modified_by', read_only=True)
558558
event_details = MiniEventSerializer(source='event', read_only=True)
559559
reporting_ns_details = MiniCountrySerializer(source='reporting_ns', read_only=True)
560560
deployed_eru_details = ERUMiniSerializer(source='deployed_eru', read_only=True)

lang/permissions.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ def has_permission(self, request, view):
1616
hasattr(request, '_request') and request.path[:6] == '/docs/' and \
1717
hasattr(view, 'basename') and view.basename == 'language':
1818
return True
19-
return String.has_perm(request.user, view.kwargs['pk'])
19+
return String.has_perm(request.user, view.kwargs.get('pk'))
2020

2121
def has_object_permission(self, request, view, obj):
2222
return self.has_permission(self, request, view)

local_units/serializers.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
from api.models import Country
66

77

8-
class CountrySerializer(ModelSerializer):
8+
class LocalUnitCountrySerializer(ModelSerializer):
99

1010
class Meta:
1111
model = Country
@@ -23,7 +23,7 @@ class Meta:
2323

2424
class LocalUnitSerializer(ModelSerializer):
2525
location = SerializerMethodField()
26-
country = CountrySerializer()
26+
country = LocalUnitCountrySerializer()
2727
type = LocalUnitTypeSerializer()
2828
class Meta:
2929
model = LocalUnit

main/exception_handler.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
'Please contact an admin to fix this issue.'
1515
)
1616

17+
logger = logging.getLogger(__name__)
18+
1719

1820
def custom_exception_handler(exc, context):
1921
# Default exception handler
@@ -45,6 +47,11 @@ def custom_exception_handler(exc, context):
4547
'non_field_errors': [standard_error_string]
4648
},
4749
}
50+
logger.error(
51+
'{}.{}'.format(type(exc).__module__, type(exc).__name__),
52+
exc_info=True,
53+
extra={'request': context.get('request')},
54+
)
4855
response = Response(response_data, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
4956

5057
return response

main/settings.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,7 @@
140140
INSTALLED_APPS = [
141141
# External App (This app has to defined before django.contrib.admin)
142142
'modeltranslation', # https://django-modeltranslation.readthedocs.io/en/latest/installation.html#installed-apps
143+
'drf_spectacular',
143144

144145
# Django Apps
145146
'django.contrib.admin',
@@ -207,7 +208,7 @@
207208
'rest_framework.renderers.BrowsableAPIRenderer',
208209
'rest_framework_csv.renderers.PaginatedCSVRenderer',
209210
),
210-
'DEFAULT_SCHEMA_CLASS': 'rest_framework.schemas.coreapi.AutoSchema',
211+
'DEFAULT_SCHEMA_CLASS': 'drf_spectacular.openapi.AutoSchema',
211212
}
212213

213214
GRAPHENE = {
@@ -558,5 +559,12 @@
558559
}
559560
CACHE_MIDDLEWARE_SECONDS = env('CACHE_MIDDLEWARE_SECONDS') # Planned: 600 for staging, 60 from prod
560561

562+
SPECTACULAR_SETTINGS = {
563+
'TITLE': 'IFRC-GO API',
564+
'DESCRIPTION': 'IFRC-GO API Documenation',
565+
'VERSION': '1.0.0',
566+
'SERVE_INCLUDE_SCHEMA': False,
567+
}
568+
561569
# Need to load this to overwrite modeltranslation module
562570
import main.translation # noqa: F401 E402

main/urls.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@
7373

7474
# DRF routes
7575
from rest_framework import routers
76-
from rest_framework.documentation import include_docs_urls
76+
from drf_spectacular.views import SpectacularAPIView, SpectacularRedocView, SpectacularSwaggerView
7777
from api import drf_views as api_views
7878
from flash_update import views as flash_views
7979
from per import drf_views as per_views
@@ -230,14 +230,17 @@
230230
url(r"^api/v2/exportperresults/", per_views.ExportAssessmentToCSVViewset.as_view()),
231231
url(r"^api/v2/local-unit/(?P<pk>\d+)", LocalUnitDetailAPIView.as_view()),
232232
url(r"^api/v2/local-unit/", LocalUnitListAPIView.as_view()),
233-
url(r"^docs/", include_docs_urls(title="IFRC GO API", public=False)),
234233
url(r"^tinymce/", include("tinymce.urls")),
235234
url(r"^$", RedirectView.as_view(url="/admin")),
236235
# url(r'^', admin.site.urls),
237236
url(r"^favicon\.ico$", RedirectView.as_view(url="/static/favicon.ico")),
238237
url(r"^server-error-for-devs", DummyHttpStatusError.as_view()),
239238
url(r"^exception-error-for-devs", DummyExceptionError.as_view()),
240239
path("i18n/", include("django.conf.urls.i18n")),
240+
# Docs
241+
path("docs/", SpectacularRedocView.as_view(url_name='schema'), name='redoc'),
242+
path("api-docs/", SpectacularAPIView.as_view(), name='schema'),
243+
path("api-docs/swagger-ui/", SpectacularSwaggerView.as_view(url_name='schema'), name='swagger-ui'),
241244
]
242245

243246
if settings.DEBUG:
@@ -248,9 +251,7 @@
248251
url("__debug__/", include(debug_toolbar.urls)),
249252
# For django versions before 2.0:
250253
# url(r'^__debug__/', include(debug_toolbar.urls)),
251-
]
252-
+ urlpatterns
253-
+ static.static(
254+
] + urlpatterns + static.static(
254255
settings.MEDIA_URL,
255256
view=xframe_options_exempt(serve),
256257
document_root=settings.MEDIA_ROOT,

per/serializers.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -142,14 +142,14 @@ class Meta:
142142
fields = ('id', 'country', 'phase', 'phase_display', 'updated_at')
143143

144144

145-
class MiniUserSerializer(serializers.ModelSerializer):
145+
class PerMiniUserSerializer(serializers.ModelSerializer):
146146
class Meta:
147147
model = User
148148
fields = ('id', 'first_name', 'last_name', 'email')
149149

150150

151151
class WorkPlanSerializer(serializers.ModelSerializer):
152-
user = MiniUserSerializer()
152+
user = PerMiniUserSerializer()
153153
prioritization_display = serializers.CharField(source='get_prioritization_display', read_only=True)
154154
status_display = serializers.CharField(source='get_status_display', read_only=True)
155155

@@ -165,7 +165,7 @@ class Meta:
165165

166166

167167
class OverviewSerializer(serializers.ModelSerializer):
168-
user = MiniUserSerializer()
168+
user = PerMiniUserSerializer()
169169
country = RegoCountrySerializer()
170170
type_of_assessment = AssessmentTypeSerializer()
171171
included_forms = serializers.CharField(source='get_included_forms', read_only=True)

0 commit comments

Comments
 (0)