|
| 1 | + |
| 2 | +# Django API Versioning |
| 3 | + |
| 4 | +[](https://badge.fury.io/py/django-api-versioning) |
| 5 | +[](https://github.com/mojtaba-arvin/django-api-versioning/actions) |
| 6 | +[](https://codecov.io/gh/mojtaba-arvin/django-api-versioning) |
| 7 | +[](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 commit comments