def get(self, request, *args, **kwargs): data = OrderedDict({ 'v1': { '_links': { 'self': { 'href': request._request.build_absolute_uri(reverse('api-root')), } }, 'version': get_version(API_VERSIONS['v1']), 'status': 'in production', }, 'version': get_version(VERSION), }) return Response(data)
def get(self, request, *args, **kwargs): response = super().get(request, *args, **kwargs) # Appending the index view with API version 1 information. For now we need to mix this with # the API version 0 index view. response.data['v1'] = { '_links': { 'self': { 'href': request._request.build_absolute_uri(reverse('v1:api-root')), } }, 'version': get_version(API_VERSIONS['v1']), 'status': 'in production', } response.data.update({ 'version': get_version(VERSION), }) return response
def __call__(self, request): response = self.get_response(request) # Checking if we're coming from a DRF view, which contains API versioning information. # If so, add a HTTP header with API version number. renderer_context = getattr(response, 'renderer_context', {}) drf_request = renderer_context.get('request', None) if drf_request and getattr(drf_request, 'version', None): response['X-API-Version'] = get_version(API_VERSIONS[drf_request.version]) return response
def __call__(self, request): # Versioning # ========== # SIA / Signalen follows the semantic versioning standard. Previously we had # separate version numbers for the V0 (now defunct) and V1 versions of the API. # We now no longer separately version these, as their releases were always # tied to the backend. For backwards compatibility, and to not break external # systems that rely on SIA / Signalen we still expose all the separate version # numbers, but they are now all the same. response = self.get_response(request) response['X-API-Version'] = get_version(VERSION) return response
def test_signals_index(self): response = self.client.get('/signals/') expected_api_version_1 = { '_links': { 'self': { 'href': 'http://testserver/signals/v1/', } }, 'version': get_version(API_VERSIONS['v1']), 'status': 'in development', } self.assertEqual(response.status_code, 200) self.assertEqual(response.json()['v1'], expected_api_version_1)
def test_http_header_api_version(self): response = self.client.get('/signals/') self.assertEqual(response['X-API-Version'], get_version(API_VERSIONS['v0']))
# This will make sure the app is always imported when # Django starts so that shared_task will use this app. from signals.celery import app as celery_app from signals.utils.version import get_version __all__ = ['celery_app', 'VERSION', 'API_VERSIONS', ] # Versioning # ========== # # We are tracking multiple versions. First we've the application version which increments by every # release. Based on the changes in the new release there is a major, minor or patch version bump. # # Besides that we've API versioning which are seperated versioning numbers for the given API. The # major versioning number of the API is fixed related to the given API. e.g. API Version 1 with url # `/signals/v1/...` will always have major API version number `1`. # Application version (Major, minor, patch) VERSION = (0, 14, 1) # API versions (Major, minor, patch) API_VERSIONS = { 'v0': (0, 8, 0), 'v1': (1, 11, 0), } __version__ = get_version(VERSION)
def test_get_version_full(self): version = (1, 2, 3) version_str = get_version(version) self.assertEqual(version_str, '1.2.3')
def test_version(self): version_str = get_version() self.assertTrue(isinstance(version_str, str)) self.assertTrue(len(version_str))
def test_get_version_without_patch(self): version = (1, 3, 0) version_str = get_version(version) self.assertEqual(version_str, '1.3')