1
|
3
|
from django.conf import settings
|
2
|
3
|
from django.urls import NoReverseMatch
|
3
|
|
|
4
|
3
|
from rest_framework.reverse import _reverse
|
5
|
3
|
from rest_framework.versioning import URLPathVersioning as BaseVersioning
|
6
|
|
|
7
|
|
|
8
|
3
|
def drf_reverse(viewname, args=None, kwargs=None, request=None, format=None, **extra):
|
9
|
|
"""
|
10
|
|
Copy and monkey-patch `rest_framework.reverse.reverse` to prevent adding unwarranted
|
11
|
|
query string parameters.
|
12
|
|
"""
|
13
|
3
|
scheme = getattr(request, 'versioning_scheme', None)
|
14
|
3
|
if scheme is not None:
|
15
|
3
|
try:
|
16
|
3
|
url = scheme.reverse(viewname, args, kwargs, request, format, **extra)
|
17
|
0
|
except NoReverseMatch:
|
18
|
|
# In case the versioning scheme reversal fails, fallback to the
|
19
|
|
# default implementation
|
20
|
0
|
url = _reverse(viewname, args, kwargs, request, format, **extra)
|
21
|
|
else:
|
22
|
3
|
url = _reverse(viewname, args, kwargs, request, format, **extra)
|
23
|
|
|
24
|
3
|
return url
|
25
|
|
|
26
|
|
|
27
|
3
|
def get_request_version(request):
|
28
|
|
"""
|
29
|
|
The API version of a request as an integer i.e., 1 or 2
|
30
|
|
"""
|
31
|
3
|
version = settings.REST_FRAMEWORK['DEFAULT_VERSION']
|
32
|
3
|
if request and hasattr(request, 'version'):
|
33
|
3
|
version = request.version
|
34
|
3
|
if version is None:
|
35
|
|
# For requests to /api/
|
36
|
3
|
return None
|
37
|
3
|
return int(version.lstrip('v'))
|
38
|
|
|
39
|
|
|
40
|
3
|
def reverse(viewname, args=None, kwargs=None, request=None, format=None, **extra):
|
41
|
3
|
if request is None or getattr(request, 'version', None) is None:
|
42
|
|
# We need the "current request" to determine the correct version to
|
43
|
|
# prepend to reverse URLs. If there is no "current request", assume
|
44
|
|
# the latest API version.
|
45
|
3
|
if kwargs is None:
|
46
|
0
|
kwargs = {}
|
47
|
3
|
if 'version' not in kwargs:
|
48
|
0
|
kwargs['version'] = settings.REST_FRAMEWORK['DEFAULT_VERSION']
|
49
|
3
|
return drf_reverse(viewname, args, kwargs, request, format, **extra)
|
50
|
|
|
51
|
|
|
52
|
3
|
class URLPathVersioning(BaseVersioning):
|
53
|
|
|
54
|
3
|
def reverse(self, viewname, args=None, kwargs=None, request=None, format=None, **extra):
|
55
|
3
|
if request.version is not None:
|
56
|
3
|
kwargs = {} if (kwargs is None) else kwargs
|
57
|
3
|
kwargs[self.version_param] = request.version
|
58
|
3
|
request = None
|
59
|
|
|
60
|
3
|
return super(BaseVersioning, self).reverse(
|
61
|
|
viewname, args, kwargs, request, format, **extra
|
62
|
|
)
|