django-small-view-set 0.2.6__tar.gz → 0.2.8__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.6 → django_small_view_set-0.2.8}/PKG-INFO +41 -29
- django_small_view_set-0.2.8/README.md +95 -0
- {django_small_view_set-0.2.6 → django_small_view_set-0.2.8}/pyproject.toml +3 -3
- {django_small_view_set-0.2.6 → django_small_view_set-0.2.8}/src/small_view_set/helpers.py +1 -1
- django_small_view_set-0.2.8/src/small_view_set/small_view_set.py +78 -0
- django_small_view_set-0.2.6/README.md +0 -83
- django_small_view_set-0.2.6/src/small_view_set/small_view_set.py +0 -232
- {django_small_view_set-0.2.6 → django_small_view_set-0.2.8}/LICENSE +0 -0
- {django_small_view_set-0.2.6 → django_small_view_set-0.2.8}/src/small_view_set/README.md +0 -0
- {django_small_view_set-0.2.6 → django_small_view_set-0.2.8}/src/small_view_set/__init__.py +0 -0
- {django_small_view_set-0.2.6 → django_small_view_set-0.2.8}/src/small_view_set/config.py +0 -0
- {django_small_view_set-0.2.6 → django_small_view_set-0.2.8}/src/small_view_set/decorators.py +0 -0
- {django_small_view_set-0.2.6 → django_small_view_set-0.2.8}/src/small_view_set/exceptions.py +0 -0
@@ -1,10 +1,10 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: django-small-view-set
|
3
|
-
Version: 0.2.
|
4
|
-
Summary: A lightweight Django ViewSet alternative with minimal abstraction
|
3
|
+
Version: 0.2.8
|
4
|
+
Summary: A lightweight and explicit Django ViewSet alternative with minimal abstraction and full async support
|
5
5
|
Home-page: https://github.com/nateonguitar/django-small-view-set
|
6
6
|
License: MIT
|
7
|
-
Keywords: django,
|
7
|
+
Keywords: django,viewset,view set,api,async,rest api,django async,lightweight
|
8
8
|
Author: Nate Brooks
|
9
9
|
Requires-Python: >=3.8
|
10
10
|
Classifier: License :: OSI Approved :: MIT License
|
@@ -19,16 +19,12 @@ Description-Content-Type: text/markdown
|
|
19
19
|
|
20
20
|
# Django Small View Set
|
21
21
|
|
22
|
-
A lightweight Django ViewSet alternative with minimal abstraction
|
22
|
+
A lightweight and explicit Django ViewSet alternative with minimal abstraction and full async support.
|
23
23
|
|
24
|
-
|
25
|
-
|
26
|
-
This guide provides a simple example to get started with the library.
|
24
|
+
Designed for clear patterns, minimal magic, and complete control over your API 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 lightweight and explicit Django ViewSet alternative with minimal abstraction and full async support.
|
4
|
+
|
5
|
+
Designed for clear patterns, minimal magic, and complete control over your API 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,13 +4,13 @@ build-backend = "poetry.core.masonry.api"
|
|
4
4
|
|
5
5
|
[tool.poetry]
|
6
6
|
name = "django-small-view-set"
|
7
|
-
version = "0.2.
|
8
|
-
description = "A lightweight Django ViewSet alternative with minimal abstraction
|
7
|
+
version = "0.2.8"
|
8
|
+
description = "A lightweight and explicit Django ViewSet alternative with minimal abstraction and full async support"
|
9
9
|
readme = "README.md"
|
10
10
|
authors = ["Nate Brooks"]
|
11
11
|
license = "MIT"
|
12
12
|
repository = "https://github.com/nateonguitar/django-small-view-set"
|
13
|
-
keywords = ["django", "
|
13
|
+
keywords = ["django", "viewset", "view set", "api", "async", "rest api", "django async", "lightweight"]
|
14
14
|
packages = [
|
15
15
|
{ include = "small_view_set", from = "src" }
|
16
16
|
]
|
@@ -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.6 → django_small_view_set-0.2.8}/src/small_view_set/decorators.py
RENAMED
File without changes
|
{django_small_view_set-0.2.6 → django_small_view_set-0.2.8}/src/small_view_set/exceptions.py
RENAMED
File without changes
|