- Author:
- agusmakmun
- Posted:
- December 11, 2019
- Language:
- Python
- Version:
- Not specified
- Score:
- 3 (after 3 ratings)
As you can see, if you using django-rest-framework, you will found many different response format. This middleware to solve all of these problems with Standard API Response.
All HTTP Response status stored into json response, not in HTTP Status (because mobile application, like android can't fetch the response body when HTTP Status >= 400).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 | # ---------------------------------- # middleware.py # ---------------------------------- import json import copy from django.utils.deprecation import MiddlewareMixin from django.utils.translation import ugettext_lazy as _ from django.core.serializers.json import DjangoJSONEncoder from rest_framework import status class BaseAPIResponseMiddleware(MiddlewareMixin): def render_response(self, response): """ function to fixed the response API following with this format: [1] success single { "status": 200, "success": true, "message": "The success message", "result": {} } [2] success list { "status": 200, "success": true, "message": null, "results": [], "count": 2, "page_size": 5, "current_page": 1, "next": "http://127.0.0.1:8000/api/page/?page=2&search=a", "previous": null } [3] failed { "status": 400, "success": false, "message": "The failed message", "result": {} } """ default_response_keys = ('status', 'status_http', 'detail', 'message', 'success', 'non_field_errors', 'count', 'page_size', 'current_page', 'next', 'previous', 'result', 'results') response_data = copy.deepcopy(response.data) # setup default result if doesn't exist if not any(['result' in response_data, 'results' in response_data]): response_data.update({'result': {}}) # setup default message into response data if 'message' not in response_data: response_data.update({'message': None}) # store the status_code into response data if 'status' not in response_data: response_data.update({'status': response.status_code}) # store the status_http into response data if 'status_http' not in response_data: response_data.update({'status_http': response.status_code}) # updating the response message if 'detail' in response_data: response_data.update({'message': response_data.get('detail')}) del response_data['detail'] elif 'non_field_errors' in response_data: response_errors = '<br />'.join(response_data.get('non_field_errors')) response_data.update({'message': response_errors}) del response_data['non_field_errors'] # store the success boolean into response data if response.status_code >= 400: response_errors = [] response_errors_keys = [] for (key, value) in response_data.items(): if key not in default_response_keys: errors = ' '.join([str(v) for v in value]) errors = '%s: %s' % (key, errors) response_errors.append(errors) response_errors_keys.append(key) if len(response_errors) > 0: response_errors = '<br />'.join(response_errors) response_data.update({'message': response_errors}) # deleting the errors in the field keys. if len(response_errors_keys) > 0: list(map(response_data.pop, response_errors_keys)) if not response_data.get('message'): response_data.update({'message': _('Failed')}) response_data.update({'success': False, 'status_http': status.HTTP_200_OK}) elif response.status_code >= 100: if not response_data.get('message'): response_data.update({'message': _('Success')}) if 'success' not in response_data: response_data.update({'success': True}) return response_data def process_response(self, request, response): if hasattr(response, 'data') and isinstance(response.data, dict): try: response_data = self.render_response(response) response.status_code = response_data.get('status_http') if 'status_http' in response_data: del response_data['status_http'] response.data = response_data response.content = json.dumps(response_data, cls=DjangoJSONEncoder) except Exception: pass return response # -------------------------------------------------------------------- # paginator.py # -------------------------------------------------------------------- from __future__ import unicode_literals from collections import OrderedDict from django.conf import settings from django.core.paginator import (Paginator, EmptyPage, PageNotAnInteger) from django.utils.translation import ugettext_lazy as _ from rest_framework import status from rest_framework.response import Response from rest_framework.pagination import (PageNumberPagination, LimitOffsetPagination) class RestPagination(PageNumberPagination, LimitOffsetPagination): """ class FoobarPagiantion(RestPagination): page_size = 10 class FoobarView(ListAPIView): pagination_class = FoobarPagiantion """ def paginate_queryset(self, queryset, request, view=None): queryset = super().paginate_queryset(queryset, request, view=view) limit = request.query_params.get('limit') if str(limit).isdigit(): return queryset[:int(limit)] return queryset def get_paginated_response(self, results): next_link = self.get_next_link() if self.get_next_link() is not None else '' prev_link = self.get_previous_link() if self.get_previous_link() is not None else '' if settings.USE_SSL: next_link = next_link.replace('http:', 'https:') prev_link = prev_link.replace('http:', 'https:') return Response(OrderedDict([ ('count', self.page.paginator.count), ('page_size', self.page_size), ('current_page', self.page.number), ('next', next_link if next_link != '' else None), ('previous', prev_link if prev_link != '' else None), ('status', status.HTTP_200_OK), ('message', _('Success')), ('success', True), ('results', results) ])) # -------------------------------------------------------------------- # settings.py # -------------------------------------------------------------------- """ MIDDLEWARE = [ .... 'path.to.middleware.BaseAPIResponseMiddleware' ] REST_FRAMEWORK = { .... 'DEFAULT_PAGINATION_CLASS': 'path.to.paginator.RestPagination' } """ |
More like this
- Template tag - list punctuation for a list of items by shapiromatron 10 months, 1 week ago
- JSONRequestMiddleware adds a .json() method to your HttpRequests by cdcarter 10 months, 2 weeks ago
- Serializer factory with Django Rest Framework by julio 1 year, 5 months ago
- Image compression before saving the new model / work with JPG, PNG by Schleidens 1 year, 6 months ago
- Help text hyperlinks by sa2812 1 year, 6 months ago
Comments
Please login first before commenting.