Skip to content

Commit f038833

Browse files
committed
Ensure support for class-based views and add corresponding test cases
1 parent 20ca043 commit f038833

File tree

3 files changed

+41
-1
lines changed

3 files changed

+41
-1
lines changed

django_api_versioning/decorators.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from functools import wraps
22
from typing import Callable, Optional, List
3+
from django.views import View
34
from .settings import api_settings as settings
45
from .registry import registry
56
from .exceptions import InvalidVersionError, VersionRangeError, VersionTypeError
@@ -41,8 +42,13 @@ def endpoint(
4142
"""
4243

4344
def decorator(func: Callable) -> Callable:
45+
4446
@wraps(func)
4547
def view(*args, **kwargs):
48+
# Check if the view is a class-based view (CBV)
49+
if isinstance(func, type) and issubclass(func, View):
50+
# For class-based views, ensure it's called as a method
51+
return func.as_view()(*args, **kwargs)
4652
return func(*args, **kwargs)
4753

4854
# Read API versioning settings

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
setup(
77
name="django-api-versioning",
8-
version="0.1.2",
8+
version="0.1.3",
99
author="Mojtaba Arvin",
1010
author_email="ArvinDevDay@gmail.com",
1111
description= (

tests/test_decorators.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
import pytest
22
from unittest.mock import patch
3+
from django.http import JsonResponse
4+
from django.views import View
35
from django_api_versioning.settings import api_settings as settings
46
from django_api_versioning.registry import registry
57
from django_api_versioning.decorators import endpoint
68
from django_api_versioning.exceptions import InvalidVersionError, VersionTypeError, VersionRangeError
79

10+
811
@pytest.fixture(autouse=True)
912
def clear_registered_routes():
1013
"""Clear the registry before each test to ensure isolation."""
@@ -86,3 +89,34 @@ def test_missing_api_version_settings():
8689
@endpoint("users", version=2)
8790
def test_view():
8891
pass
92+
93+
def test_class_based_view(mock_settings):
94+
# Create a class-based view and decorate it with the `endpoint` decorator
95+
@endpoint("users", version=2)
96+
class UsersView(View):
97+
def get(self, request):
98+
return JsonResponse({"message": "API Version 2 Users"})
99+
100+
# Register the view and check if the route is correctly registered
101+
registered_routes = [str(p.pattern) for p in registry.urlpatterns]
102+
assert "api/v2/users" in registered_routes, f"Route for version 2 is missing: {registered_routes}"
103+
104+
def test_class_based_view_with_invalid_version(mock_settings):
105+
# Test invalid version for class-based view
106+
with pytest.raises(InvalidVersionError):
107+
@endpoint("users", version=4)
108+
class UsersView(View):
109+
def get(self, request):
110+
return JsonResponse({"message": "API Version 4 Users"})
111+
112+
def test_class_based_view_with_backward_compatibility(mock_settings):
113+
# Test class-based view with backward compatibility
114+
@endpoint("users", version=3)
115+
class UsersView(View):
116+
def get(self, request):
117+
return JsonResponse({"message": "API Version 3 Users"})
118+
119+
registered_routes = [str(p.pattern) for p in registry.urlpatterns]
120+
# Assert that versions 1, 2, and 3 are registered for backward compatibility
121+
for version in range(1, 4):
122+
assert f"api/v{version}/users" in registered_routes, f"Missing route for v{version}: {registered_routes}"

0 commit comments

Comments
 (0)