django-small-view-set 0.2.5__tar.gz → 0.2.7__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {django_small_view_set-0.2.5 → django_small_view_set-0.2.7}/PKG-INFO +39 -27
- django_small_view_set-0.2.7/README.md +95 -0
- {django_small_view_set-0.2.5 → django_small_view_set-0.2.7}/pyproject.toml +1 -1
- {django_small_view_set-0.2.5 → django_small_view_set-0.2.7}/src/small_view_set/decorators.py +6 -4
- {django_small_view_set-0.2.5 → django_small_view_set-0.2.7}/src/small_view_set/helpers.py +1 -1
- django_small_view_set-0.2.7/src/small_view_set/small_view_set.py +78 -0
- django_small_view_set-0.2.5/README.md +0 -83
- django_small_view_set-0.2.5/src/small_view_set/small_view_set.py +0 -232
- {django_small_view_set-0.2.5 → django_small_view_set-0.2.7}/LICENSE +0 -0
- {django_small_view_set-0.2.5 → django_small_view_set-0.2.7}/src/small_view_set/README.md +0 -0
- {django_small_view_set-0.2.5 → django_small_view_set-0.2.7}/src/small_view_set/__init__.py +0 -0
- {django_small_view_set-0.2.5 → django_small_view_set-0.2.7}/src/small_view_set/config.py +0 -0
- {django_small_view_set-0.2.5 → django_small_view_set-0.2.7}/src/small_view_set/exceptions.py +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: django-small-view-set
|
3
|
-
Version: 0.2.
|
3
|
+
Version: 0.2.7
|
4
4
|
Summary: A lightweight Django ViewSet alternative with minimal abstraction.
|
5
5
|
Home-page: https://github.com/nateonguitar/django-small-view-set
|
6
6
|
License: MIT
|
@@ -19,16 +19,12 @@ Description-Content-Type: text/markdown
|
|
19
19
|
|
20
20
|
# Django Small View Set
|
21
21
|
|
22
|
-
A lightweight Django ViewSet
|
22
|
+
A recommended pattern and a lightweight Django ViewSet with minimal abstraction.
|
23
23
|
|
24
|
-
|
25
|
-
|
26
|
-
This guide provides a simple example to get started with the library.
|
24
|
+
This pattern supports both standard endpoints and `async` endpoints.
|
27
25
|
|
28
26
|
### Example Usage
|
29
27
|
|
30
|
-
Here’s how to define a basic view set:
|
31
|
-
|
32
28
|
In settings.py
|
33
29
|
```python
|
34
30
|
# Register SmallViewSetConfig in settings
|
@@ -37,43 +33,60 @@ from small_view_set SmallViewSetConfig
|
|
37
33
|
SMALL_VIEW_SET_CONFIG = SmallViewSetConfig()
|
38
34
|
```
|
39
35
|
|
36
|
+
^^^ This will get you up and running, but it is recommended to write your own [Custom exception handler](./README_CUSTOM_EXCEPTION_HANDLER.md)
|
37
|
+
|
38
|
+
Please note, endpoints cannot be registered in `urls.py` with the
|
39
|
+
request method (like POST, or GET), therefore create a `collection` and/or `detail` orchestrator
|
40
|
+
method for the standard CRUD operations.
|
41
|
+
|
40
42
|
|
41
43
|
```python
|
42
44
|
import asyncio
|
43
45
|
from django.http import JsonResponse
|
44
46
|
from django.urls import path
|
45
47
|
from small_view_set import SmallViewSet, endpoint, endpoint_disabled
|
48
|
+
from urllib.request import Request
|
46
49
|
|
47
50
|
class BarViewSet(SmallViewSet):
|
48
51
|
|
49
52
|
def urlpatterns(self):
|
50
53
|
return [
|
51
|
-
path('api/bars/', self.
|
52
|
-
path('api/bars
|
53
|
-
path('api/bars
|
54
|
+
path('api/bars/', self.collection, name='bars_collection'),
|
55
|
+
path('api/bars/<int:pk>/', self.detail, name='bars_detail'),
|
56
|
+
path('api/bars/items/', self.items, name='bars_items'),
|
54
57
|
]
|
58
|
+
@endpoint(allowed_methods=['GET', 'POST'])
|
59
|
+
def collection(self, request: Request):
|
60
|
+
if request.method == 'GET':
|
61
|
+
return self.list(request)
|
62
|
+
raise MethodNotAllowed(request.method)
|
63
|
+
|
64
|
+
@endpoint(allowed_methods=['GET', 'PATCH'])
|
65
|
+
async def detail(self, request: Request, pk: int):
|
66
|
+
if request.method == 'GET':
|
67
|
+
return await self.retrieve(request, pk)
|
68
|
+
elif request.method == 'PATCH':
|
69
|
+
return self.patch(request, pk)
|
70
|
+
raise MethodNotAllowed(request.method)
|
55
71
|
|
56
|
-
@endpoint(allowed_methods=['GET'])
|
57
72
|
def list(self, request):
|
58
73
|
self.protect_list(request)
|
59
74
|
return JsonResponse({"message": "Hello, world!"}, status=200)
|
60
75
|
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
self.protect_list(request)
|
65
|
-
await asyncio.sleep(1)
|
66
|
-
return JsonResponse({"message": "List of items"}, status=200)
|
76
|
+
async def retrieve(self, request: Request, pk: int):
|
77
|
+
self.protect_retrieve(request)
|
78
|
+
return JsonResponse({"message": f"Detail for ID {pk}"}, status=200)
|
67
79
|
|
68
|
-
|
69
|
-
def patch(self, request, pk):
|
80
|
+
def patch(self, request: Request, pk: int):
|
70
81
|
self.protect_update(request)
|
71
82
|
return JsonResponse({"message": f"Updated {pk}"}, status=200)
|
72
83
|
|
73
84
|
@endpoint(allowed_methods=['GET'])
|
74
|
-
async def
|
75
|
-
|
76
|
-
|
85
|
+
async def items(self, request: Request):
|
86
|
+
# Pick the closest protect that matches the endoint. `GET items` is closest to a list
|
87
|
+
self.protect_list(request)
|
88
|
+
await asyncio.sleep(1)
|
89
|
+
return JsonResponse({"message": "List of items"}, status=200)
|
77
90
|
```
|
78
91
|
|
79
92
|
|
@@ -92,12 +105,11 @@ urlpatterns = [
|
|
92
105
|
```
|
93
106
|
|
94
107
|
|
95
|
-
##
|
108
|
+
## Deeper learning
|
96
109
|
|
97
|
-
- [Custom
|
98
|
-
- [
|
99
|
-
- [
|
100
|
-
- [DRF Compatibility](./README_DRF_COMPATIBILITY.md): Learn how to use some of Django Rest Framework's tools, like Serializers.
|
110
|
+
- [Custom protections](./README_CUSTOM_PROTECTIONS.md): Learn how to subclass `SmallViewSet` to add custom protections like logged-in checks.
|
111
|
+
- [Custom exception handler](./README_CUSTOM_EXCEPTION_HANDLER.md): Understand how to write your own exception handler.
|
112
|
+
- [DRF compatibility](./README_DRF_COMPATIBILITY.md): Learn how to use some of Django Rest Framework's tools, like Serializers.
|
101
113
|
- [Disabling an endpoint](./README_DISABLE_ENDPOINT.md): Learn how to disable an endpoint without needing to delete it or comment it out.
|
102
114
|
- [Reason](./README_REASON.md): Reasoning behind this package.
|
103
115
|
|
@@ -0,0 +1,95 @@
|
|
1
|
+
# Django Small View Set
|
2
|
+
|
3
|
+
A recommended pattern and a lightweight Django ViewSet with minimal abstraction.
|
4
|
+
|
5
|
+
This pattern supports both standard endpoints and `async` endpoints.
|
6
|
+
|
7
|
+
### Example Usage
|
8
|
+
|
9
|
+
In settings.py
|
10
|
+
```python
|
11
|
+
# Register SmallViewSetConfig in settings
|
12
|
+
from small_view_set SmallViewSetConfig
|
13
|
+
|
14
|
+
SMALL_VIEW_SET_CONFIG = SmallViewSetConfig()
|
15
|
+
```
|
16
|
+
|
17
|
+
^^^ This will get you up and running, but it is recommended to write your own [Custom exception handler](./README_CUSTOM_EXCEPTION_HANDLER.md)
|
18
|
+
|
19
|
+
Please note, endpoints cannot be registered in `urls.py` with the
|
20
|
+
request method (like POST, or GET), therefore create a `collection` and/or `detail` orchestrator
|
21
|
+
method for the standard CRUD operations.
|
22
|
+
|
23
|
+
|
24
|
+
```python
|
25
|
+
import asyncio
|
26
|
+
from django.http import JsonResponse
|
27
|
+
from django.urls import path
|
28
|
+
from small_view_set import SmallViewSet, endpoint, endpoint_disabled
|
29
|
+
from urllib.request import Request
|
30
|
+
|
31
|
+
class BarViewSet(SmallViewSet):
|
32
|
+
|
33
|
+
def urlpatterns(self):
|
34
|
+
return [
|
35
|
+
path('api/bars/', self.collection, name='bars_collection'),
|
36
|
+
path('api/bars/<int:pk>/', self.detail, name='bars_detail'),
|
37
|
+
path('api/bars/items/', self.items, name='bars_items'),
|
38
|
+
]
|
39
|
+
@endpoint(allowed_methods=['GET', 'POST'])
|
40
|
+
def collection(self, request: Request):
|
41
|
+
if request.method == 'GET':
|
42
|
+
return self.list(request)
|
43
|
+
raise MethodNotAllowed(request.method)
|
44
|
+
|
45
|
+
@endpoint(allowed_methods=['GET', 'PATCH'])
|
46
|
+
async def detail(self, request: Request, pk: int):
|
47
|
+
if request.method == 'GET':
|
48
|
+
return await self.retrieve(request, pk)
|
49
|
+
elif request.method == 'PATCH':
|
50
|
+
return self.patch(request, pk)
|
51
|
+
raise MethodNotAllowed(request.method)
|
52
|
+
|
53
|
+
def list(self, request):
|
54
|
+
self.protect_list(request)
|
55
|
+
return JsonResponse({"message": "Hello, world!"}, status=200)
|
56
|
+
|
57
|
+
async def retrieve(self, request: Request, pk: int):
|
58
|
+
self.protect_retrieve(request)
|
59
|
+
return JsonResponse({"message": f"Detail for ID {pk}"}, status=200)
|
60
|
+
|
61
|
+
def patch(self, request: Request, pk: int):
|
62
|
+
self.protect_update(request)
|
63
|
+
return JsonResponse({"message": f"Updated {pk}"}, status=200)
|
64
|
+
|
65
|
+
@endpoint(allowed_methods=['GET'])
|
66
|
+
async def items(self, request: Request):
|
67
|
+
# Pick the closest protect that matches the endoint. `GET items` is closest to a list
|
68
|
+
self.protect_list(request)
|
69
|
+
await asyncio.sleep(1)
|
70
|
+
return JsonResponse({"message": "List of items"}, status=200)
|
71
|
+
```
|
72
|
+
|
73
|
+
|
74
|
+
## Registering in `urls.py`
|
75
|
+
|
76
|
+
To register the viewset in your `urls.py`:
|
77
|
+
|
78
|
+
```python
|
79
|
+
from api.views.bar import BarViewSet
|
80
|
+
|
81
|
+
urlpatterns = [
|
82
|
+
# Other URLs like admin, static, etc.
|
83
|
+
|
84
|
+
*BarViewSet().urlpatterns(),
|
85
|
+
]
|
86
|
+
```
|
87
|
+
|
88
|
+
|
89
|
+
## Deeper learning
|
90
|
+
|
91
|
+
- [Custom protections](./README_CUSTOM_PROTECTIONS.md): Learn how to subclass `SmallViewSet` to add custom protections like logged-in checks.
|
92
|
+
- [Custom exception handler](./README_CUSTOM_EXCEPTION_HANDLER.md): Understand how to write your own exception handler.
|
93
|
+
- [DRF compatibility](./README_DRF_COMPATIBILITY.md): Learn how to use some of Django Rest Framework's tools, like Serializers.
|
94
|
+
- [Disabling an endpoint](./README_DISABLE_ENDPOINT.md): Learn how to disable an endpoint without needing to delete it or comment it out.
|
95
|
+
- [Reason](./README_REASON.md): Reasoning behind this package.
|
@@ -4,7 +4,7 @@ build-backend = "poetry.core.masonry.api"
|
|
4
4
|
|
5
5
|
[tool.poetry]
|
6
6
|
name = "django-small-view-set"
|
7
|
-
version = "0.2.
|
7
|
+
version = "0.2.7"
|
8
8
|
description = "A lightweight Django ViewSet alternative with minimal abstraction."
|
9
9
|
readme = "README.md"
|
10
10
|
authors = ["Nate Brooks"]
|
{django_small_view_set-0.2.5 → django_small_view_set-0.2.7}/src/small_view_set/decorators.py
RENAMED
@@ -10,6 +10,7 @@ def endpoint(
|
|
10
10
|
func_name = func.__name__
|
11
11
|
def sync_wrapper(viewset, *args, **kwargs):
|
12
12
|
request = args[0]
|
13
|
+
args = args[1:]
|
13
14
|
try:
|
14
15
|
config: SmallViewSetConfig = getattr(settings, 'SMALL_VIEW_SET_CONFIG', SmallViewSetConfig())
|
15
16
|
pre_response = config.options_and_head_handler(request, allowed_methods)
|
@@ -17,14 +18,15 @@ def endpoint(
|
|
17
18
|
return pre_response
|
18
19
|
pk = kwargs.pop('pk', None)
|
19
20
|
if pk is None:
|
20
|
-
return func(viewset, request=request)
|
21
|
+
return func(viewset, request=request, *args, **kwargs)
|
21
22
|
else:
|
22
|
-
return func(viewset, request=request, pk=pk)
|
23
|
+
return func(viewset, request=request, pk=pk, *args, **kwargs)
|
23
24
|
except Exception as e:
|
24
25
|
return config.exception_handler(request, func_name, e)
|
25
26
|
|
26
27
|
async def async_wrapper(viewset, *args, **kwargs):
|
27
28
|
request = args[0]
|
29
|
+
args = args[1:]
|
28
30
|
try:
|
29
31
|
config: SmallViewSetConfig = getattr(settings, 'SMALL_VIEW_SET_CONFIG', SmallViewSetConfig())
|
30
32
|
pre_response = config.options_and_head_handler(request, allowed_methods)
|
@@ -32,9 +34,9 @@ def endpoint(
|
|
32
34
|
return pre_response
|
33
35
|
pk = kwargs.pop('pk', None)
|
34
36
|
if pk is None:
|
35
|
-
return await func(viewset, request=request)
|
37
|
+
return await func(viewset, request=request, *args, **kwargs)
|
36
38
|
else:
|
37
|
-
return await func(viewset, request=request, pk=pk)
|
39
|
+
return await func(viewset, request=request, pk=pk, *args, **kwargs)
|
38
40
|
except Exception as e:
|
39
41
|
return config.exception_handler(request, func_name, e)
|
40
42
|
|
@@ -18,7 +18,7 @@ if not _logger.hasHandlers():
|
|
18
18
|
_logger.setLevel(logging.INFO)
|
19
19
|
|
20
20
|
|
21
|
-
def default_options_and_head_handler(request, allowed_methods: list[str]):
|
21
|
+
def default_options_and_head_handler(request: Request, allowed_methods: list[str]):
|
22
22
|
if request.method == 'OPTIONS':
|
23
23
|
response = JsonResponse(
|
24
24
|
data=None,
|
@@ -0,0 +1,78 @@
|
|
1
|
+
import json
|
2
|
+
import logging
|
3
|
+
from urllib.request import Request
|
4
|
+
|
5
|
+
from .exceptions import BadRequest
|
6
|
+
|
7
|
+
logger = logging.getLogger('app')
|
8
|
+
|
9
|
+
class SmallViewSet:
|
10
|
+
def parse_json_body(self, request: Request):
|
11
|
+
if request.content_type != 'application/json':
|
12
|
+
raise BadRequest('Invalid content type')
|
13
|
+
return json.loads(request.body)
|
14
|
+
|
15
|
+
def protect_create(self, request: Request):
|
16
|
+
"""
|
17
|
+
Stub for adding any custom business logic to protect the create method.
|
18
|
+
For example:
|
19
|
+
- Check if the user is authenticated
|
20
|
+
- Check if the user has validated their email
|
21
|
+
- Throttle requests
|
22
|
+
|
23
|
+
Recommended to call super().protect_create(request) in the subclass in case
|
24
|
+
this library adds logic in the future.
|
25
|
+
"""
|
26
|
+
pass
|
27
|
+
|
28
|
+
def protect_list(self, request: Request):
|
29
|
+
"""
|
30
|
+
Stub for adding any custom business logic to protect the list method.
|
31
|
+
For example:
|
32
|
+
- Check if the user is authenticated
|
33
|
+
- Check if the user has validated their email
|
34
|
+
- Throttle requests
|
35
|
+
|
36
|
+
Recommended to call super().protect_create(request) in the subclass in case
|
37
|
+
this library adds logic in the future.
|
38
|
+
"""
|
39
|
+
pass
|
40
|
+
|
41
|
+
def protect_retrieve(self, request: Request):
|
42
|
+
"""
|
43
|
+
Stub for adding any custom business logic to protect the retrieve method.
|
44
|
+
For example:
|
45
|
+
- Check if the user is authenticated
|
46
|
+
- Check if the user has validated their email
|
47
|
+
- Throttle requests
|
48
|
+
|
49
|
+
Recommended to call super().protect_create(request) in the subclass in case
|
50
|
+
this library adds logic in the future.
|
51
|
+
"""
|
52
|
+
pass
|
53
|
+
|
54
|
+
def protect_update(self, request: Request):
|
55
|
+
"""
|
56
|
+
Stub for adding any custom business logic to protect the update method.
|
57
|
+
For example:
|
58
|
+
- Check if the user is authenticated
|
59
|
+
- Check if the user has validated their email
|
60
|
+
- Throttle requests
|
61
|
+
|
62
|
+
Recommended to call super().protect_create(request) in the subclass in case
|
63
|
+
this library adds logic in the future.
|
64
|
+
"""
|
65
|
+
pass
|
66
|
+
|
67
|
+
def protect_delete(self, request: Request):
|
68
|
+
"""
|
69
|
+
Stub for adding any custom business logic to protect the delete method.
|
70
|
+
For example:
|
71
|
+
- Check if the user is authenticated
|
72
|
+
- Check if the user has validated their email
|
73
|
+
- Throttle requests
|
74
|
+
|
75
|
+
Recommended to call super().protect_create(request) in the subclass in case
|
76
|
+
this library adds logic in the future.
|
77
|
+
"""
|
78
|
+
pass
|
@@ -1,83 +0,0 @@
|
|
1
|
-
# Django Small View Set
|
2
|
-
|
3
|
-
A lightweight Django ViewSet alternative with minimal abstraction. This library provides a simple and transparent way to define API endpoints without relying on complex abstractions.
|
4
|
-
|
5
|
-
## Getting Started with Django Small View Set
|
6
|
-
|
7
|
-
This guide provides a simple example to get started with the library.
|
8
|
-
|
9
|
-
### Example Usage
|
10
|
-
|
11
|
-
Here’s how to define a basic view set:
|
12
|
-
|
13
|
-
In settings.py
|
14
|
-
```python
|
15
|
-
# Register SmallViewSetConfig in settings
|
16
|
-
from small_view_set SmallViewSetConfig
|
17
|
-
|
18
|
-
SMALL_VIEW_SET_CONFIG = SmallViewSetConfig()
|
19
|
-
```
|
20
|
-
|
21
|
-
|
22
|
-
```python
|
23
|
-
import asyncio
|
24
|
-
from django.http import JsonResponse
|
25
|
-
from django.urls import path
|
26
|
-
from small_view_set import SmallViewSet, endpoint, endpoint_disabled
|
27
|
-
|
28
|
-
class BarViewSet(SmallViewSet):
|
29
|
-
|
30
|
-
def urlpatterns(self):
|
31
|
-
return [
|
32
|
-
path('api/bars/', self.default_router, name='bars_collection'),
|
33
|
-
path('api/bars/items/', self.items, name='bars_items'),
|
34
|
-
path('api/bars/<int:pk>/', self.default_router, name='bars_detail'),
|
35
|
-
]
|
36
|
-
|
37
|
-
@endpoint(allowed_methods=['GET'])
|
38
|
-
def list(self, request):
|
39
|
-
self.protect_list(request)
|
40
|
-
return JsonResponse({"message": "Hello, world!"}, status=200)
|
41
|
-
|
42
|
-
@endpoint(allowed_methods=['GET'])
|
43
|
-
@endpoint_disabled
|
44
|
-
async def items(self, request):
|
45
|
-
self.protect_list(request)
|
46
|
-
await asyncio.sleep(1)
|
47
|
-
return JsonResponse({"message": "List of items"}, status=200)
|
48
|
-
|
49
|
-
@endpoint(allowed_methods=['PATCH'])
|
50
|
-
def patch(self, request, pk):
|
51
|
-
self.protect_update(request)
|
52
|
-
return JsonResponse({"message": f"Updated {pk}"}, status=200)
|
53
|
-
|
54
|
-
@endpoint(allowed_methods=['GET'])
|
55
|
-
async def retrieve(self, request, pk):
|
56
|
-
self.protect_retrieve(request)
|
57
|
-
return JsonResponse({"message": f"Detail for ID {pk}"}, status=200)
|
58
|
-
```
|
59
|
-
|
60
|
-
|
61
|
-
## Registering in `urls.py`
|
62
|
-
|
63
|
-
To register the viewset in your `urls.py`:
|
64
|
-
|
65
|
-
```python
|
66
|
-
from api.views.bar import BarViewSet
|
67
|
-
|
68
|
-
urlpatterns = [
|
69
|
-
# Other URLs like admin, static, etc.
|
70
|
-
|
71
|
-
*BarViewSet().urlpatterns(),
|
72
|
-
]
|
73
|
-
```
|
74
|
-
|
75
|
-
|
76
|
-
## Documentation
|
77
|
-
|
78
|
-
- [Custom Endpoints](./README_CUSTOM_ENDPOINT.md): Learn how to define custom endpoints alongside the default router.
|
79
|
-
- [Handling Endpoint Exceptions](./README_HANDLE_ENDPOINT_EXCEPTIONS.md): Understand how to write your own decorators for exception handling.
|
80
|
-
- [Custom Protections](./README_CUSTOM_PROTECTIONS.md): Learn how to subclass `SmallViewSet` to add custom protections like logged-in checks.
|
81
|
-
- [DRF Compatibility](./README_DRF_COMPATIBILITY.md): Learn how to use some of Django Rest Framework's tools, like Serializers.
|
82
|
-
- [Disabling an endpoint](./README_DISABLE_ENDPOINT.md): Learn how to disable an endpoint without needing to delete it or comment it out.
|
83
|
-
- [Reason](./README_REASON.md): Reasoning behind this package.
|
@@ -1,232 +0,0 @@
|
|
1
|
-
import inspect
|
2
|
-
import json
|
3
|
-
import logging
|
4
|
-
from urllib.request import Request
|
5
|
-
|
6
|
-
|
7
|
-
from .decorators import endpoint
|
8
|
-
from .exceptions import BadRequest, MethodNotAllowed
|
9
|
-
|
10
|
-
logger = logging.getLogger('app')
|
11
|
-
|
12
|
-
class SmallViewSet:
|
13
|
-
def parse_json_body(self, request: Request):
|
14
|
-
if request.content_type != 'application/json':
|
15
|
-
raise BadRequest('Invalid content type')
|
16
|
-
return json.loads(request.body)
|
17
|
-
|
18
|
-
def protect_create(self, request: Request):
|
19
|
-
"""
|
20
|
-
Stub for adding any custom business logic to protect the create method.
|
21
|
-
For example:
|
22
|
-
- Check if the user is authenticated
|
23
|
-
- Check if the user has validated their email
|
24
|
-
- Throttle requests
|
25
|
-
|
26
|
-
Recommended to call super().protect_create(request) in the subclass in case
|
27
|
-
this library adds logic in the future.
|
28
|
-
"""
|
29
|
-
pass
|
30
|
-
|
31
|
-
def protect_list(self, request: Request):
|
32
|
-
"""
|
33
|
-
Stub for adding any custom business logic to protect the list method.
|
34
|
-
For example:
|
35
|
-
- Check if the user is authenticated
|
36
|
-
- Check if the user has validated their email
|
37
|
-
- Throttle requests
|
38
|
-
|
39
|
-
Recommended to call super().protect_create(request) in the subclass in case
|
40
|
-
this library adds logic in the future.
|
41
|
-
"""
|
42
|
-
pass
|
43
|
-
|
44
|
-
def protect_retrieve(self, request: Request):
|
45
|
-
"""
|
46
|
-
Stub for adding any custom business logic to protect the retrieve method.
|
47
|
-
For example:
|
48
|
-
- Check if the user is authenticated
|
49
|
-
- Check if the user has validated their email
|
50
|
-
- Throttle requests
|
51
|
-
|
52
|
-
Recommended to call super().protect_create(request) in the subclass in case
|
53
|
-
this library adds logic in the future.
|
54
|
-
"""
|
55
|
-
pass
|
56
|
-
|
57
|
-
def protect_update(self, request: Request):
|
58
|
-
"""
|
59
|
-
Stub for adding any custom business logic to protect the update method.
|
60
|
-
For example:
|
61
|
-
- Check if the user is authenticated
|
62
|
-
- Check if the user has validated their email
|
63
|
-
- Throttle requests
|
64
|
-
|
65
|
-
Recommended to call super().protect_create(request) in the subclass in case
|
66
|
-
this library adds logic in the future.
|
67
|
-
"""
|
68
|
-
pass
|
69
|
-
|
70
|
-
def protect_delete(self, request: Request):
|
71
|
-
"""
|
72
|
-
Stub for adding any custom business logic to protect the delete method.
|
73
|
-
For example:
|
74
|
-
- Check if the user is authenticated
|
75
|
-
- Check if the user has validated their email
|
76
|
-
- Throttle requests
|
77
|
-
|
78
|
-
Recommended to call super().protect_create(request) in the subclass in case
|
79
|
-
this library adds logic in the future.
|
80
|
-
"""
|
81
|
-
pass
|
82
|
-
|
83
|
-
@endpoint(allowed_methods=['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS', 'HEAD'])
|
84
|
-
async def default_router_async(self, request: Request, pk=None, *args, **kwargs):
|
85
|
-
"""
|
86
|
-
This method routes requests to the appropriate method based on the HTTP method and presence of a primary key (pk).
|
87
|
-
|
88
|
-
It also handles errors and returns appropriate JSON responses by using the decorator @endpoint(allowed_method=[]).
|
89
|
-
|
90
|
-
GET/POST for collection endpoints and GET/PUT/PATCH/DELETE for detail endpoints.
|
91
|
-
|
92
|
-
Example:
|
93
|
-
```
|
94
|
-
# Note: AppViewSet is a subclass of SmallViewSet with overridden protect methods with more specific logic.
|
95
|
-
|
96
|
-
class CommentViewSet(AppViewSet):
|
97
|
-
def urlpatterns(self):
|
98
|
-
return [
|
99
|
-
path('api/comments/', self.default_router_async, name='comments_collection'),
|
100
|
-
path('api/comments/<int:pk>/', self.default_router_async, name='comments_detail'),
|
101
|
-
path('api/comments/<int:pk>/custom_put/', self.custom_put, name='comments_custom_put_detail'),
|
102
|
-
]
|
103
|
-
|
104
|
-
@endpoint(allowed_method=['POST'])
|
105
|
-
def create(self, request: Request):
|
106
|
-
self.protect_create(request)
|
107
|
-
. . .
|
108
|
-
|
109
|
-
@endpoint(allowed_method=['PUT', 'PATCH'])
|
110
|
-
def update(self, request: Request, pk: int):
|
111
|
-
self.protect_update(request)
|
112
|
-
. . .
|
113
|
-
|
114
|
-
@endpoint(allowed_method=['PUT'])
|
115
|
-
def custom_put(self, request: Request, pk: int):
|
116
|
-
self.protect_update(request)
|
117
|
-
. . .
|
118
|
-
|
119
|
-
@endpoint(allowed_method=['GET'])
|
120
|
-
@disable_endpoint
|
121
|
-
def some_disabled_endpoint(self, request: Request):
|
122
|
-
self.protect_retrieve(request)
|
123
|
-
. . .
|
124
|
-
```
|
125
|
-
"""
|
126
|
-
func = None
|
127
|
-
if pk is None:
|
128
|
-
if request.method == 'GET':
|
129
|
-
if hasattr(self, 'list'):
|
130
|
-
func = self.list
|
131
|
-
|
132
|
-
elif request.method == 'POST':
|
133
|
-
if hasattr(self, 'create'):
|
134
|
-
func = self.create
|
135
|
-
else:
|
136
|
-
if request.method == 'GET':
|
137
|
-
if hasattr(self, 'retrieve'):
|
138
|
-
func = self.retrieve
|
139
|
-
|
140
|
-
elif request.method == 'PUT':
|
141
|
-
if hasattr(self, 'put'):
|
142
|
-
func = self.put
|
143
|
-
|
144
|
-
elif request.method == 'PATCH':
|
145
|
-
if hasattr(self, 'patch'):
|
146
|
-
func = self.patch
|
147
|
-
|
148
|
-
elif request.method == 'DELETE':
|
149
|
-
if hasattr(self, 'delete'):
|
150
|
-
func = self.delete
|
151
|
-
|
152
|
-
if func is None:
|
153
|
-
raise MethodNotAllowed(request.method)
|
154
|
-
if pk is not None:
|
155
|
-
kwargs['pk'] = pk
|
156
|
-
return await func(request, *args, **kwargs)
|
157
|
-
|
158
|
-
|
159
|
-
@endpoint(allowed_methods=['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS', 'HEAD'])
|
160
|
-
def default_router(self, request: Request, pk=None, *args, **kwargs):
|
161
|
-
"""
|
162
|
-
This method routes requests to the appropriate method based on the HTTP method and presence of a primary key (pk).
|
163
|
-
|
164
|
-
It also handles errors and returns appropriate JSON responses by using the decorator @endpoint(allowed_method=[]).
|
165
|
-
|
166
|
-
GET/POST for collection endpoints and GET/PUT/PATCH/DELETE for detail endpoints.
|
167
|
-
|
168
|
-
Example:
|
169
|
-
```
|
170
|
-
# Note: AppViewSet is a subclass of SmallViewSet with overridden protect methods with more specific logic.
|
171
|
-
|
172
|
-
class CommentViewSet(AppViewSet):
|
173
|
-
def urlpatterns(self):
|
174
|
-
return [
|
175
|
-
path('api/comments/', self.default_router, name='comments_collection'),
|
176
|
-
path('api/comments/<int:pk>/', self.default_router, name='comments_detail'),
|
177
|
-
path('api/comments/<int:pk>/custom_put/', self.custom_put, name='comments_custom_put_detail'),
|
178
|
-
]
|
179
|
-
|
180
|
-
@endpoint(allowed_method=['POST'])
|
181
|
-
def create(self, request: Request):
|
182
|
-
self.protect_create(request)
|
183
|
-
. . .
|
184
|
-
|
185
|
-
@endpoint(allowed_method=['PUT', 'PATCH'])
|
186
|
-
def update(self, request: Request, pk: int):
|
187
|
-
self.protect_update(request)
|
188
|
-
. . .
|
189
|
-
|
190
|
-
@endpoint(allowed_method=['PUT'])
|
191
|
-
def custom_put(self, request: Request, pk: int):
|
192
|
-
self.protect_update(request)
|
193
|
-
. . .
|
194
|
-
|
195
|
-
@disable_endpoint
|
196
|
-
@endpoint(allowed_method=['GET'])
|
197
|
-
def some_disabled_endpoint(self, request: Request):
|
198
|
-
self.protect_retrieve(request)
|
199
|
-
. . .
|
200
|
-
```
|
201
|
-
"""
|
202
|
-
func = None
|
203
|
-
if pk is None:
|
204
|
-
if request.method == 'GET':
|
205
|
-
if hasattr(self, 'list'):
|
206
|
-
func = self.list
|
207
|
-
|
208
|
-
elif request.method == 'POST':
|
209
|
-
if hasattr(self, 'create'):
|
210
|
-
func = self.create
|
211
|
-
else:
|
212
|
-
if request.method == 'GET':
|
213
|
-
if hasattr(self, 'retrieve'):
|
214
|
-
func = self.retrieve
|
215
|
-
|
216
|
-
elif request.method == 'PUT':
|
217
|
-
if hasattr(self, 'put'):
|
218
|
-
func = self.put
|
219
|
-
|
220
|
-
elif request.method == 'PATCH':
|
221
|
-
if hasattr(self, 'patch'):
|
222
|
-
func = self.patch
|
223
|
-
|
224
|
-
elif request.method == 'DELETE':
|
225
|
-
if hasattr(self, 'delete'):
|
226
|
-
func = self.delete
|
227
|
-
|
228
|
-
if func is None:
|
229
|
-
raise MethodNotAllowed(request.method)
|
230
|
-
if pk is not None:
|
231
|
-
kwargs['pk'] = pk
|
232
|
-
return func(request, *args, **kwargs)
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{django_small_view_set-0.2.5 → django_small_view_set-0.2.7}/src/small_view_set/exceptions.py
RENAMED
File without changes
|