django-api-versioning 0.1.0__tar.gz

Sign up to get free protection for your applications and to get access to all the features.
Files changed (28) hide show
  1. django-api-versioning-0.1.0/.pre-commit-config.yaml +44 -0
  2. django-api-versioning-0.1.0/LICENSE +21 -0
  3. django-api-versioning-0.1.0/MANIFEST.in +8 -0
  4. django-api-versioning-0.1.0/PKG-INFO +250 -0
  5. django-api-versioning-0.1.0/README.md +226 -0
  6. django-api-versioning-0.1.0/django_api_versioning/__init__.py +0 -0
  7. django-api-versioning-0.1.0/django_api_versioning/decorators.py +88 -0
  8. django-api-versioning-0.1.0/django_api_versioning/exceptions.py +18 -0
  9. django-api-versioning-0.1.0/django_api_versioning/registry.py +33 -0
  10. django-api-versioning-0.1.0/django_api_versioning/settings.py +77 -0
  11. django-api-versioning-0.1.0/django_api_versioning/urls.py +5 -0
  12. django-api-versioning-0.1.0/django_api_versioning.egg-info/PKG-INFO +250 -0
  13. django-api-versioning-0.1.0/django_api_versioning.egg-info/SOURCES.txt +26 -0
  14. django-api-versioning-0.1.0/django_api_versioning.egg-info/dependency_links.txt +1 -0
  15. django-api-versioning-0.1.0/django_api_versioning.egg-info/requires.txt +13 -0
  16. django-api-versioning-0.1.0/django_api_versioning.egg-info/top_level.txt +2 -0
  17. django-api-versioning-0.1.0/pyproject.toml +16 -0
  18. django-api-versioning-0.1.0/pytest.ini +4 -0
  19. django-api-versioning-0.1.0/requirements-dev.txt +11 -0
  20. django-api-versioning-0.1.0/requirements.txt +1 -0
  21. django-api-versioning-0.1.0/setup.cfg +4 -0
  22. django-api-versioning-0.1.0/setup.py +48 -0
  23. django-api-versioning-0.1.0/tests/__init__.py +0 -0
  24. django-api-versioning-0.1.0/tests/test_decorators.py +88 -0
  25. django-api-versioning-0.1.0/tests/test_exceptions.py +19 -0
  26. django-api-versioning-0.1.0/tests/test_registry.py +83 -0
  27. django-api-versioning-0.1.0/tests/test_settings.py +147 -0
  28. django-api-versioning-0.1.0/tests/test_urls.py +33 -0
@@ -0,0 +1,44 @@
1
+ repos:
2
+
3
+ # Black for code formatting
4
+ - repo: https://github.com/psf/black
5
+ rev: 23.3.0 # version of black
6
+ hooks:
7
+ - id: black
8
+ language_version: python3.9
9
+ files: \.py$
10
+
11
+ # isort for sorting imports
12
+ - repo: https://github.com/pre-commit/mirrors-isort
13
+ rev: v5.10.1 # version of isort
14
+ hooks:
15
+ - id: isort
16
+ language_version: python3.9
17
+ files: \.py$
18
+
19
+ # Flake8 for linting
20
+ - repo: https://github.com/PyCQA/flake8
21
+ rev: 5.0.4 # version of flake8
22
+ hooks:
23
+ - id: flake8
24
+ language_version: python3.9
25
+ files: \.py$
26
+
27
+ # mypy for type checking
28
+ - repo: https://github.com/pre-commit/mirrors-mypy
29
+ rev: v0.991 # version of mypy
30
+ hooks:
31
+ - id: mypy
32
+ language_version: python3.9
33
+ files: \.py$
34
+
35
+ # # Pytest for testing
36
+ # - repo: https://github.com/pre-commit/mirrors-pytest
37
+ # rev: v6.0.0 # version of pytest
38
+ # hooks:
39
+ # - id: pytest
40
+ # name: "Run tests with pytest"
41
+ # entry: pytest
42
+ # language: system # using the system's pytest
43
+ # types: [python]
44
+ # files: \.py$
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) [year] [Full name]
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,8 @@
1
+ include README.md
2
+ include LICENSE
3
+ include .pre-commit-config.yaml
4
+ recursive-include django_api_versioning *.py
5
+ recursive-include tests *.py
6
+ include requirements.txt
7
+ include requirements-dev.txt
8
+ include pytest.ini
@@ -0,0 +1,250 @@
1
+ Metadata-Version: 2.1
2
+ Name: django-api-versioning
3
+ Version: 0.1.0
4
+ Summary: A powerful and flexible library for managing API versioning in Django projects.
5
+ Home-page: https://github.com/mojtaba-arvin/django-api-versioning
6
+ Author: Mojtaba Arvin
7
+ Author-email: ArvinDevDay@gmail.com
8
+ License: UNKNOWN
9
+ Platform: UNKNOWN
10
+ Classifier: Programming Language :: Python :: 3
11
+ Classifier: Programming Language :: Python :: 3.9
12
+ Classifier: Framework :: Django
13
+ Classifier: Framework :: Django :: 3.2
14
+ Classifier: Development Status :: 3 - Alpha
15
+ Classifier: Intended Audience :: Developers
16
+ Classifier: License :: OSI Approved :: MIT License
17
+ Classifier: Operating System :: OS Independent
18
+ Requires-Python: >=3.9
19
+ Description-Content-Type: text/markdown
20
+ Provides-Extra: dev
21
+ License-File: LICENSE
22
+
23
+
24
+ # Django API Versioning
25
+
26
+ [![PyPI version](https://badge.fury.io/py/django-api-versioning.svg)](https://badge.fury.io/py/django-api-versioning)
27
+ [![Build Status](https://github.com/mojtaba-arvin/django-api-versioning/actions/workflows/tests.yml/badge.svg)](https://github.com/mojtaba-arvin/django-api-versioning/actions)
28
+ [![codecov](https://codecov.io/gh/mojtaba-arvin/django-api-versioning/branch/main/graph/badge.svg)](https://codecov.io/gh/mojtaba-arvin/django-api-versioning)
29
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
30
+
31
+ **Django API Versioning** is a powerful and flexible library for managing API versioning in Django projects. It allows you to easily define and manage different versions of your API endpoints using decorators, ensuring backward compatibility and clean code organization.
32
+
33
+ ## Features
34
+
35
+ - **Easy Versioning**: Define API versions using simple decorators.
36
+ - **Backward Compatibility**: Automatically register routes for all versions up to the specified version.
37
+ - **Automatic Registration:** Views are **automatically** registered for each version specified, so there is no need to manually register each version in your `urls.py`.
38
+ - **Customizable Settings**: Configure API base path, minimum and maximum versions, and more.
39
+ - **Type Checking**: Full support for type hints and static type checking with `mypy`.
40
+ - **Testing Ready**: Includes comprehensive test suite and pre-commit hooks for code quality.
41
+
42
+ ## Installation
43
+
44
+ You can install Django API Versioning via pip:
45
+
46
+ ```bash
47
+ pip install django-api-versioning
48
+ ```
49
+
50
+ ## Quick Start
51
+
52
+ 1. ### Add to Django Settings:
53
+
54
+ ```python
55
+ INSTALLED_APPS = [
56
+ ...
57
+ 'django_api_versioning',
58
+ ...
59
+ ]
60
+ ```
61
+
62
+ 2. ### Define API Settings:
63
+
64
+ ```python
65
+
66
+ API_BASE_PATH = "api/v{version}/"
67
+ API_MIN_VERSION = 1
68
+ API_MAX_VERSION = 3
69
+ ```
70
+
71
+ 3. ### Register API urls:
72
+
73
+ if you don't use any `ROOT_URLCONF` in settings you can use this:
74
+
75
+ ```python
76
+ ROOT_URLCONF = 'django_api_versioning.urls'
77
+ ```
78
+
79
+ or you have already have a `ROOT_URLCONF` in settings, you only need to import them into your root `urls.py`:
80
+
81
+ ```python
82
+ from django.urls import path, include
83
+ from django_api_versioning.urls import urlpatterns as api_urlpatterns
84
+
85
+ urlpatterns = [
86
+ # other paths here
87
+
88
+ # use empty `route` param and use `API_BASE_PATH` in settings as prefix
89
+ path('', include(api_urlpatterns)),
90
+ ]
91
+
92
+ ```
93
+
94
+ 3. ### Use the Decorator:
95
+
96
+ The `endpoint` decorator can be used in both function-based views (FBVs) and class-based views (CBVs). It's also fully compatible with `Django Rest Framework (DRF)`. The decorator allows you to define versioning for your API views and supports backward compatibility by default and you don't need to pass `backward=True` flag to the `endpoint` decorator.
97
+
98
+
99
+ #### Example for Function-Based Views (FBVs):
100
+
101
+ ```python
102
+ from django_api_versioning.decorators import endpoint
103
+ from django.http import HttpResponse
104
+
105
+ @endpoint("users", version=2, app_name='account_app', view_name="users_list_api")
106
+ def users_view(request):
107
+ return HttpResponse("API Version 2 Users")
108
+ ```
109
+
110
+ In this example, the `users_view` function is decorated with the endpoint decorator. This specifies that the view is accessible under version `2` of the API and **supports backward compatibility**. The `backward=True` flag as default ensures that users can also access the previous version (version `1`) at `/api/v1/account_app/users`.
111
+
112
+ #### Example for Class-Based Views (CBVs):
113
+ For class-based views, you can apply the decorator to methods such as `get`, `post`, or any other HTTP method you need to handle. Here’s an example:
114
+
115
+ ```python
116
+
117
+ from django_api_versioning.decorators import endpoint
118
+ from django.http import JsonResponse
119
+ from django.views import View
120
+
121
+ @endpoint("users", version=2, app_name='account_app', view_name="users_list_api")
122
+ class UsersView(View):
123
+
124
+ def get(self, request):
125
+ return JsonResponse({"message": "API Version 2 Users"})
126
+
127
+ ```
128
+
129
+ #### Integration with Django Rest Framework (DRF):
130
+
131
+ If you have already installed [Django Rest Framework](https://www.django-rest-framework.org/#installation), the `endpoint` decorator can be easily applied to APIView or viewsets. Here’s an example with a DRF APIView:
132
+
133
+
134
+ ```python
135
+ from rest_framework.views import APIView
136
+ from rest_framework.response import Response
137
+ from django_api_versioning.decorators import endpoint
138
+
139
+ @endpoint("users", version=2, app_name='account_app', view_name="users_list_api")
140
+ class UsersAPIView(APIView):
141
+
142
+ def get(self, request):
143
+ return Response({"message": "API Version 2 Users"})
144
+ ```
145
+
146
+ #### URL Generation Based on Versioning:
147
+ Once the decorator is applied, the URLs for your API will be generated based on the version specified in the decorator. For example, if the `API_MIN_VERSION` in your settings.py is set to `1` and the version in the decorator is set to `2`, the following URLs will be available:
148
+
149
+ * `/api/v1/account_app/users`
150
+ * `/api/v2/account_app/users`
151
+
152
+ The `API_MIN_VERSION` setting ensures that users can access the API using different versions, providing backward compatibility. You can adjust which versions are considered valid by modifying the `API_MIN_VERSION` and `version` numbers in the decorators.
153
+
154
+ #### Additional Configuration Options:
155
+
156
+ **Without `app_name`:** If you don't pass `app_name` in the decorator, like this:
157
+ ```python
158
+ @endpoint("users", version=2, view_name="users_list_api")
159
+ ```
160
+
161
+ The generated URLs will be:
162
+
163
+ * `/api/v1/users`
164
+ * `/api/v2/users`
165
+
166
+
167
+ **Without `version`:** If you don't pass `version` in the decorator, like this:
168
+
169
+ ```python
170
+ @endpoint("users", view_name="users_list_api")
171
+ ```
172
+
173
+ API versioning will be disabled (`API_BASE_PATH` as prefix will be removed) for that view. The only URL generated will be:
174
+
175
+ * `/users`
176
+
177
+ **Setting `backward=False`:** By default, the `backward` parameter is set to `True`, which ensures backward compatibility. If you explicitly set `backward=False`, like this:
178
+
179
+ ```python
180
+ @endpoint("users", version=2, backward=False, view_name="users_list_api")
181
+ ```
182
+
183
+ The generated URL will be only version 2:
184
+
185
+ * `api/v2/users`
186
+
187
+ 4. Run the Server:
188
+
189
+ ```bash
190
+ python manage.py runserver
191
+ ```
192
+
193
+ ## Notes
194
+ ### 1. `API_BASE_PATH` in settings Must Include ‍‍`{version}`:
195
+ The `API_BASE_PATH` should always include `{version}` to ensure proper API versioning. This is important for correctly mapping API routes to different versions.
196
+
197
+ ### 2. Using `app_name` in the `endpoint` decorator:
198
+ It's recommended to fill in the `app_name` in the `endpoint` decorator to make the API URLs **more unique and organized**. This ensures that the routes are scoped under the correct app, avoiding potential conflicts and making them easier to manage.
199
+
200
+ ### 3. Views with Version Less Than `API_MIN_VERSION` Are Automatically Ignored:
201
+ Any view whose `version` is less than the `API_MIN_VERSION` will be automatically ignored. This means clients will no longer have access to these older versions, **without the need to manually edit or remove code**. This is handled automatically by the package.
202
+
203
+ ### 4. URLs for Versions Between `API_MIN_VERSION` <= `version` <= `API_MAX_VERSION`:
204
+ Endpoints that have versions within the range defined by `API_MIN_VERSION` <= `version` <= `API_MAX_VERSION` will always have a corresponding URL generated. This ensures that only valid versions will be accessible, providing flexibility in version management.
205
+
206
+ ### `endpoint` Decorator Function Definition
207
+
208
+ The `endpoint` decorator is designed to register API views with versioning support in a Django application. It provides flexibility in managing versioned endpoints and ensures backward compatibility with previous versions of the API.
209
+
210
+ ```python
211
+ def endpoint(
212
+ postfix: str,
213
+ version: Optional[int] = None,
214
+ backward: bool = True,
215
+ app_name: Optional[str] = None,
216
+ view_name: Optional[str] = None,
217
+ ) -> Callable:
218
+ """
219
+ Decorator to register API views with versioning support.
220
+
221
+ - Uses `API_MIN_VERSION` and `API_MAX_VERSION` from Django settings.
222
+ - Supports backward compatibility by registering multiple versions if needed.
223
+ - Ensures that no version lower than `API_MIN_VERSION` is registered.
224
+
225
+ Args:
226
+ postfix (str): The endpoint suffix (e.g., "users" → "api/v1/users").
227
+ version (Optional[int]): The version of the API. Defaults to None (unversioned).
228
+ backward (bool): If True, registers routes for all versions from `API_MIN_VERSION` up to the current version, which is less than or equal to `API_MAX_VERSION`. Defaults to True.
229
+ app_name (Optional[str]): The app name to be prefixed to the route.
230
+ view_name (Optional[str]): The custom view name for Django.
231
+
232
+ Returns:
233
+ Callable: The decorated view function.
234
+
235
+ Raises:
236
+ VersionTypeError: If the provided `version` is not an integer.
237
+ VersionRangeError: If `API_MIN_VERSION` or `API_MAX_VERSION` are not properly set.
238
+ """
239
+ ```
240
+
241
+
242
+ ## Contributing
243
+
244
+ Feel free to open an issue or submit a pull request with any improvements or bug fixes. We appreciate contributions to enhance this package!
245
+
246
+ ## License
247
+
248
+ This package is open-source and available under the MIT license.
249
+
250
+
@@ -0,0 +1,226 @@
1
+
2
+ # Django API Versioning
3
+
4
+ [![PyPI version](https://badge.fury.io/py/django-api-versioning.svg)](https://badge.fury.io/py/django-api-versioning)
5
+ [![Build Status](https://github.com/mojtaba-arvin/django-api-versioning/actions/workflows/tests.yml/badge.svg)](https://github.com/mojtaba-arvin/django-api-versioning/actions)
6
+ [![codecov](https://codecov.io/gh/mojtaba-arvin/django-api-versioning/branch/main/graph/badge.svg)](https://codecov.io/gh/mojtaba-arvin/django-api-versioning)
7
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
8
+
9
+ **Django API Versioning** is a powerful and flexible library for managing API versioning in Django projects. It allows you to easily define and manage different versions of your API endpoints using decorators, ensuring backward compatibility and clean code organization.
10
+
11
+ ## Features
12
+
13
+ - **Easy Versioning**: Define API versions using simple decorators.
14
+ - **Backward Compatibility**: Automatically register routes for all versions up to the specified version.
15
+ - **Automatic Registration:** Views are **automatically** registered for each version specified, so there is no need to manually register each version in your `urls.py`.
16
+ - **Customizable Settings**: Configure API base path, minimum and maximum versions, and more.
17
+ - **Type Checking**: Full support for type hints and static type checking with `mypy`.
18
+ - **Testing Ready**: Includes comprehensive test suite and pre-commit hooks for code quality.
19
+
20
+ ## Installation
21
+
22
+ You can install Django API Versioning via pip:
23
+
24
+ ```bash
25
+ pip install django-api-versioning
26
+ ```
27
+
28
+ ## Quick Start
29
+
30
+ 1. ### Add to Django Settings:
31
+
32
+ ```python
33
+ INSTALLED_APPS = [
34
+ ...
35
+ 'django_api_versioning',
36
+ ...
37
+ ]
38
+ ```
39
+
40
+ 2. ### Define API Settings:
41
+
42
+ ```python
43
+
44
+ API_BASE_PATH = "api/v{version}/"
45
+ API_MIN_VERSION = 1
46
+ API_MAX_VERSION = 3
47
+ ```
48
+
49
+ 3. ### Register API urls:
50
+
51
+ if you don't use any `ROOT_URLCONF` in settings you can use this:
52
+
53
+ ```python
54
+ ROOT_URLCONF = 'django_api_versioning.urls'
55
+ ```
56
+
57
+ or you have already have a `ROOT_URLCONF` in settings, you only need to import them into your root `urls.py`:
58
+
59
+ ```python
60
+ from django.urls import path, include
61
+ from django_api_versioning.urls import urlpatterns as api_urlpatterns
62
+
63
+ urlpatterns = [
64
+ # other paths here
65
+
66
+ # use empty `route` param and use `API_BASE_PATH` in settings as prefix
67
+ path('', include(api_urlpatterns)),
68
+ ]
69
+
70
+ ```
71
+
72
+ 3. ### Use the Decorator:
73
+
74
+ The `endpoint` decorator can be used in both function-based views (FBVs) and class-based views (CBVs). It's also fully compatible with `Django Rest Framework (DRF)`. The decorator allows you to define versioning for your API views and supports backward compatibility by default and you don't need to pass `backward=True` flag to the `endpoint` decorator.
75
+
76
+
77
+ #### Example for Function-Based Views (FBVs):
78
+
79
+ ```python
80
+ from django_api_versioning.decorators import endpoint
81
+ from django.http import HttpResponse
82
+
83
+ @endpoint("users", version=2, app_name='account_app', view_name="users_list_api")
84
+ def users_view(request):
85
+ return HttpResponse("API Version 2 Users")
86
+ ```
87
+
88
+ In this example, the `users_view` function is decorated with the endpoint decorator. This specifies that the view is accessible under version `2` of the API and **supports backward compatibility**. The `backward=True` flag as default ensures that users can also access the previous version (version `1`) at `/api/v1/account_app/users`.
89
+
90
+ #### Example for Class-Based Views (CBVs):
91
+ For class-based views, you can apply the decorator to methods such as `get`, `post`, or any other HTTP method you need to handle. Here’s an example:
92
+
93
+ ```python
94
+
95
+ from django_api_versioning.decorators import endpoint
96
+ from django.http import JsonResponse
97
+ from django.views import View
98
+
99
+ @endpoint("users", version=2, app_name='account_app', view_name="users_list_api")
100
+ class UsersView(View):
101
+
102
+ def get(self, request):
103
+ return JsonResponse({"message": "API Version 2 Users"})
104
+
105
+ ```
106
+
107
+ #### Integration with Django Rest Framework (DRF):
108
+
109
+ If you have already installed [Django Rest Framework](https://www.django-rest-framework.org/#installation), the `endpoint` decorator can be easily applied to APIView or viewsets. Here’s an example with a DRF APIView:
110
+
111
+
112
+ ```python
113
+ from rest_framework.views import APIView
114
+ from rest_framework.response import Response
115
+ from django_api_versioning.decorators import endpoint
116
+
117
+ @endpoint("users", version=2, app_name='account_app', view_name="users_list_api")
118
+ class UsersAPIView(APIView):
119
+
120
+ def get(self, request):
121
+ return Response({"message": "API Version 2 Users"})
122
+ ```
123
+
124
+ #### URL Generation Based on Versioning:
125
+ Once the decorator is applied, the URLs for your API will be generated based on the version specified in the decorator. For example, if the `API_MIN_VERSION` in your settings.py is set to `1` and the version in the decorator is set to `2`, the following URLs will be available:
126
+
127
+ * `/api/v1/account_app/users`
128
+ * `/api/v2/account_app/users`
129
+
130
+ The `API_MIN_VERSION` setting ensures that users can access the API using different versions, providing backward compatibility. You can adjust which versions are considered valid by modifying the `API_MIN_VERSION` and `version` numbers in the decorators.
131
+
132
+ #### Additional Configuration Options:
133
+
134
+ **Without `app_name`:** If you don't pass `app_name` in the decorator, like this:
135
+ ```python
136
+ @endpoint("users", version=2, view_name="users_list_api")
137
+ ```
138
+
139
+ The generated URLs will be:
140
+
141
+ * `/api/v1/users`
142
+ * `/api/v2/users`
143
+
144
+
145
+ **Without `version`:** If you don't pass `version` in the decorator, like this:
146
+
147
+ ```python
148
+ @endpoint("users", view_name="users_list_api")
149
+ ```
150
+
151
+ API versioning will be disabled (`API_BASE_PATH` as prefix will be removed) for that view. The only URL generated will be:
152
+
153
+ * `/users`
154
+
155
+ **Setting `backward=False`:** By default, the `backward` parameter is set to `True`, which ensures backward compatibility. If you explicitly set `backward=False`, like this:
156
+
157
+ ```python
158
+ @endpoint("users", version=2, backward=False, view_name="users_list_api")
159
+ ```
160
+
161
+ The generated URL will be only version 2:
162
+
163
+ * `api/v2/users`
164
+
165
+ 4. Run the Server:
166
+
167
+ ```bash
168
+ python manage.py runserver
169
+ ```
170
+
171
+ ## Notes
172
+ ### 1. `API_BASE_PATH` in settings Must Include ‍‍`{version}`:
173
+ The `API_BASE_PATH` should always include `{version}` to ensure proper API versioning. This is important for correctly mapping API routes to different versions.
174
+
175
+ ### 2. Using `app_name` in the `endpoint` decorator:
176
+ It's recommended to fill in the `app_name` in the `endpoint` decorator to make the API URLs **more unique and organized**. This ensures that the routes are scoped under the correct app, avoiding potential conflicts and making them easier to manage.
177
+
178
+ ### 3. Views with Version Less Than `API_MIN_VERSION` Are Automatically Ignored:
179
+ Any view whose `version` is less than the `API_MIN_VERSION` will be automatically ignored. This means clients will no longer have access to these older versions, **without the need to manually edit or remove code**. This is handled automatically by the package.
180
+
181
+ ### 4. URLs for Versions Between `API_MIN_VERSION` <= `version` <= `API_MAX_VERSION`:
182
+ Endpoints that have versions within the range defined by `API_MIN_VERSION` <= `version` <= `API_MAX_VERSION` will always have a corresponding URL generated. This ensures that only valid versions will be accessible, providing flexibility in version management.
183
+
184
+ ### `endpoint` Decorator Function Definition
185
+
186
+ The `endpoint` decorator is designed to register API views with versioning support in a Django application. It provides flexibility in managing versioned endpoints and ensures backward compatibility with previous versions of the API.
187
+
188
+ ```python
189
+ def endpoint(
190
+ postfix: str,
191
+ version: Optional[int] = None,
192
+ backward: bool = True,
193
+ app_name: Optional[str] = None,
194
+ view_name: Optional[str] = None,
195
+ ) -> Callable:
196
+ """
197
+ Decorator to register API views with versioning support.
198
+
199
+ - Uses `API_MIN_VERSION` and `API_MAX_VERSION` from Django settings.
200
+ - Supports backward compatibility by registering multiple versions if needed.
201
+ - Ensures that no version lower than `API_MIN_VERSION` is registered.
202
+
203
+ Args:
204
+ postfix (str): The endpoint suffix (e.g., "users" → "api/v1/users").
205
+ version (Optional[int]): The version of the API. Defaults to None (unversioned).
206
+ backward (bool): If True, registers routes for all versions from `API_MIN_VERSION` up to the current version, which is less than or equal to `API_MAX_VERSION`. Defaults to True.
207
+ app_name (Optional[str]): The app name to be prefixed to the route.
208
+ view_name (Optional[str]): The custom view name for Django.
209
+
210
+ Returns:
211
+ Callable: The decorated view function.
212
+
213
+ Raises:
214
+ VersionTypeError: If the provided `version` is not an integer.
215
+ VersionRangeError: If `API_MIN_VERSION` or `API_MAX_VERSION` are not properly set.
216
+ """
217
+ ```
218
+
219
+
220
+ ## Contributing
221
+
222
+ Feel free to open an issue or submit a pull request with any improvements or bug fixes. We appreciate contributions to enhance this package!
223
+
224
+ ## License
225
+
226
+ This package is open-source and available under the MIT license.
@@ -0,0 +1,88 @@
1
+ from functools import wraps
2
+ from typing import Callable, Optional, List
3
+ from .settings import api_settings as settings
4
+ from .registry import registry
5
+ from .exceptions import InvalidVersionError, VersionRangeError, VersionTypeError
6
+
7
+
8
+ def endpoint(
9
+ postfix: str,
10
+ version: Optional[int] = None,
11
+ backward: bool = True,
12
+ app_name: Optional[str] = None,
13
+ view_name: Optional[str] = None,
14
+ ) -> Callable:
15
+ """
16
+ Decorator to register API views with versioning support.
17
+
18
+ - Uses `API_MIN_VERSION` and `API_MAX_VERSION` from Django settings.
19
+ - Supports backward compatibility by registering multiple versions if needed.
20
+ - Ensures that no version lower than `API_MIN_VERSION` is registered.
21
+
22
+ Args:
23
+ postfix (str): The endpoint suffix (e.g., "users" → "api/v1/users").
24
+ version (Optional[int]): The version of the API. Defaults to None (unversioned).
25
+ backward (bool): If True, registers routes for all versions from `API_MIN_VERSION` up to the current version, which is less than or equal to `API_MAX_VERSION`. Defaults to True.
26
+ app_name (Optional[str]): The app name to be prefixed to the route.
27
+ view_name (Optional[str]): The custom view name for Django.
28
+
29
+ Returns:
30
+ Callable: The decorated view function.
31
+
32
+ Raises:
33
+ VersionTypeError: If the provided `version` is not an integer.
34
+ VersionRangeError: If `API_MIN_VERSION` or `API_MAX_VERSION` are not properly set.
35
+ """
36
+
37
+ def decorator(func: Callable) -> Callable:
38
+ @wraps(func)
39
+ def view(*args, **kwargs):
40
+ return func(*args, **kwargs)
41
+
42
+ # Read API versioning settings
43
+ min_version: int = getattr(settings, "API_MIN_VERSION", 1)
44
+ max_version: int = getattr(settings, "API_MAX_VERSION", 1)
45
+
46
+ if not isinstance(min_version, int) or not isinstance(max_version, int):
47
+ raise VersionRangeError("API_MIN_VERSION and API_MAX_VERSION must be integers.")
48
+
49
+ if min_version > max_version:
50
+ raise VersionRangeError("API_MIN_VERSION cannot be greater than API_MAX_VERSION.")
51
+
52
+ if version is not None and not isinstance(version, int):
53
+ raise VersionTypeError("Version must be an integer or None.")
54
+
55
+ if version is not None and version > max_version:
56
+ raise InvalidVersionError(f"Version {version} is above the maximum allowed version {max_version}.")
57
+
58
+ app_name_part: str = f"{app_name}/" if app_name else ""
59
+
60
+ def _register_route(ver: Optional[int]) -> None:
61
+ """Helper function to register a route in the registry."""
62
+ if ver is None:
63
+ base_path = "" # No version prefix
64
+ else:
65
+ base_path = settings.API_BASE_PATH.format(version=ver)
66
+ route = f"{base_path}{app_name_part}{postfix}"
67
+ registry.register(route, view, view_name)
68
+
69
+ def _get_valid_versions() -> List[Optional[int]]:
70
+ """Returns a list of valid versions to register."""
71
+ if version is None:
72
+ # If no version is given, register only the unversioned route
73
+ return [None] # Just register the unversioned route
74
+ if version < min_version:
75
+ return [] # Ignore versions below min_version
76
+ if backward:
77
+ return list(range(min_version, version + 1)) # Register all versions up to the given version
78
+ return [version] # Only register the specified version when backward is False
79
+
80
+ # Register valid versions
81
+ valid_versions = _get_valid_versions()
82
+
83
+ for ver in valid_versions:
84
+ _register_route(ver)
85
+
86
+ return view
87
+
88
+ return decorator
@@ -0,0 +1,18 @@
1
+ class VersioningError(Exception):
2
+ """Raised when there is a general error in API versioning."""
3
+ pass
4
+
5
+
6
+ class InvalidVersionError(VersioningError):
7
+ """Raised when an invalid API version is used."""
8
+ pass
9
+
10
+
11
+ class VersionRangeError(VersioningError):
12
+ """Raised when the version range is not valid (e.g., min_version > max_version)."""
13
+ pass
14
+
15
+
16
+ class VersionTypeError(VersioningError):
17
+ """Raised when the version type is invalid (e.g., not an integer)."""
18
+ pass