Skip to content

Commit ca8935d

Browse files
authored
Merge pull request #6 from freemindcore/feat/more-configuration
Feat/more configuration
2 parents 7bee3a2 + 35e2a34 commit ca8935d

File tree

7 files changed

+67
-60
lines changed

7 files changed

+67
-60
lines changed

.bumpversion.cfg

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
[bumpversion]
2-
current_version = 0.1.18
2+
current_version = 0.1.19
33
commit = True
44
tag = True
55
parse = (?P<major>\d+)\.(?P<feat>\d+)\.(?P<patch>\d+)

easy/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
"""Django Easy API - Easy and Fast Django REST framework based on Django-ninja-extra"""
22

3-
__version__ = "0.1.18"
3+
__version__ = "0.1.19"
44

55
from easy.main import EasyAPI
66

easy/controller/meta.py

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
from ninja_extra.pagination import paginate
1212

1313
from easy.domain.orm import CrudModel
14+
from easy.response import BaseApiResponse
1415
from easy.services import BaseService
1516
from easy.utils import copy_func
1617

@@ -32,14 +33,25 @@ async def get_obj(self, request: HttpRequest, id: int) -> Any:
3233
GET /{id}
3334
Retrieve a single Object
3435
"""
35-
return await self.service.get_obj(id)
36+
try:
37+
qs = await self.service.get_obj(id)
38+
except Exception as e: # pragma: no cover
39+
logger.error(f"Get Error - {e}", exc_info=True)
40+
return BaseApiResponse(str(e), message="Get Failed", errno=500)
41+
if qs:
42+
return qs
43+
else:
44+
return BaseApiResponse(message="Not Found", errno=404)
3645

3746
async def del_obj(self, request: HttpRequest, id: int) -> Any:
3847
"""
3948
DELETE /{id}
4049
Delete a single Object
4150
"""
42-
return await self.service.del_obj(id)
51+
if await self.service.del_obj(id):
52+
return BaseApiResponse("Deleted.", errno=204)
53+
else:
54+
return BaseApiResponse("Not Found.", errno=404)
4355

4456
@paginate
4557
async def get_objs(
@@ -140,7 +152,11 @@ async def add_obj( # type: ignore
140152
PUT /
141153
Create a single Object
142154
"""
143-
return await self.service.add_obj(**data.dict())
155+
obj_id = await self.service.add_obj(**data.dict())
156+
if obj_id:
157+
return BaseApiResponse({"id": obj_id}, errno=201)
158+
else:
159+
return BaseApiResponse("Add failed", errno=204) # pragma: no cover
144160

145161
async def patch_obj( # type: ignore
146162
self, request: HttpRequest, id: int, data: DataSchema
@@ -149,7 +165,10 @@ async def patch_obj( # type: ignore
149165
PATCH /{id}
150166
Update a single field for a Object
151167
"""
152-
return await self.service.patch_obj(id=id, payload=data.dict())
168+
if await self.service.patch_obj(id=id, payload=data.dict()):
169+
return BaseApiResponse("Updated.")
170+
else:
171+
return BaseApiResponse("Update Failed", errno=400)
153172

154173
DataSchema.__name__ = (
155174
f"{opts_model.__name__}__AutoSchema({str(uuid.uuid4())[:4]})"

easy/domain/orm.py

Lines changed: 38 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
import logging
22
from typing import Any, Dict, List, Tuple, Type
33

4-
from django.db import models
4+
from django.db import models, transaction
55
from django.db.models.query import QuerySet
66
from ninja_extra.shortcuts import get_object_or_none
77

8-
from easy.response import BaseApiResponse
8+
from easy.exception import BaseAPIException
99

1010
logger = logging.getLogger(__name__)
1111

@@ -19,7 +19,7 @@ def __init__(self, model: Type[models.Model]):
1919
if isinstance(_field, models.ManyToManyField)
2020
)
2121

22-
def __separate_payload(self, payload: Dict) -> Tuple[Dict, Dict]:
22+
def _separate_payload(self, payload: Dict) -> Tuple[Dict, Dict]:
2323
m2m_fields = {}
2424
local_fields = {}
2525
for _field in payload.keys():
@@ -35,70 +35,60 @@ def __separate_payload(self, payload: Dict) -> Tuple[Dict, Dict]:
3535
local_fields.update({_field: payload[_field]})
3636
return local_fields, m2m_fields
3737

38+
@staticmethod
39+
def _crud_set_m2m_obj(obj: models.Model, m2m_fields: Dict) -> None:
40+
if obj and m2m_fields:
41+
for _field, _value in m2m_fields.items():
42+
if _value and isinstance(_value, List):
43+
m2m_f = getattr(obj, _field)
44+
m2m_f.set(_value)
45+
3846
# Define BASE CRUD
47+
@transaction.atomic()
3948
def _crud_add_obj(self, **payload: Dict) -> Any:
40-
local_f_payload, m2m_f_payload = self.__separate_payload(payload)
41-
# Create obj with local_fields payload
49+
local_f_payload, m2m_f_payload = self._separate_payload(payload)
50+
4251
try:
52+
# Create obj with local_fields payload
4353
obj = self.model.objects.create(**local_f_payload)
54+
# Save obj with m2m_fields payload
55+
self._crud_set_m2m_obj(obj, m2m_f_payload)
4456
except Exception as e: # pragma: no cover
45-
logger.error(f"Crud_add Error - {e}", exc_info=True)
46-
return BaseApiResponse(str(e), message="Add failed", errno=500)
47-
# Save obj with m2m_fields payload
48-
if m2m_f_payload:
49-
for _field, _value in m2m_f_payload.items():
50-
if _value and isinstance(_value, List):
51-
m2m_f = getattr(obj, _field)
52-
m2m_f.set(_value)
53-
return BaseApiResponse({"id": obj.pk}, errno=201)
57+
raise BaseAPIException(f"Create Error - {e}")
58+
if obj:
59+
return obj.id
5460

55-
def _crud_del_obj(self, pk: int) -> "BaseApiResponse":
61+
def _crud_del_obj(self, pk: int) -> bool:
5662
obj = get_object_or_none(self.model, pk=pk)
5763
if obj:
5864
self.model.objects.filter(pk=pk).delete()
59-
return BaseApiResponse("Deleted.", errno=204)
65+
return True
6066
else:
61-
return BaseApiResponse("Not Found.", errno=404)
67+
return False
6268

63-
def _crud_update_obj(self, pk: int, payload: Dict) -> "BaseApiResponse":
64-
local_fields, m2m_fields = self.__separate_payload(payload)
69+
@transaction.atomic()
70+
def _crud_update_obj(self, pk: int, payload: Dict) -> bool:
71+
local_fields, m2m_fields = self._separate_payload(payload)
6572
if not self.model.objects.filter(pk=pk).exists():
66-
return BaseApiResponse("Not Found.", errno=404)
73+
return False
6774
try:
6875
obj, _ = self.model.objects.update_or_create(pk=pk, defaults=local_fields)
76+
self._crud_set_m2m_obj(obj, m2m_fields)
6977
except Exception as e: # pragma: no cover
70-
logger.error(f"Crud_update Error - {e}", exc_info=True)
71-
return BaseApiResponse(str(e), message="Update Failed", errno=500)
72-
if obj and m2m_fields:
73-
for _field, _value in m2m_fields.items():
74-
if _value:
75-
m2m_f = getattr(obj, _field)
76-
try:
77-
m2m_f.set(_value)
78-
except Exception as e: # pragma: no cover
79-
logger.error(f"Crud_update Error - {e}", exc_info=True)
80-
return BaseApiResponse(
81-
str(e), message="Update Failed", errno=500
82-
)
83-
return BaseApiResponse({"pk": pk}, message="Updated.")
78+
raise BaseAPIException(f"Update Error - {e}")
79+
return bool(obj)
8480

8581
def _crud_get_obj(self, pk: int) -> Any:
86-
try:
87-
if self.m2m_fields_list:
88-
qs = self.model.objects.filter(pk=pk).prefetch_related(
89-
self.m2m_fields_list[0].name
90-
)
91-
for f in self.m2m_fields_list[1:]:
92-
qs = qs.prefetch_related(f.name)
93-
else:
94-
qs = self.model.objects.filter(pk=pk)
95-
except Exception as e: # pragma: no cover
96-
logger.error(f"Get Error - {e}", exc_info=True)
97-
return BaseApiResponse(str(e), message="Get Failed", errno=500)
82+
if self.m2m_fields_list:
83+
qs = self.model.objects.filter(pk=pk).prefetch_related(
84+
self.m2m_fields_list[0].name
85+
)
86+
for f in self.m2m_fields_list[1:]:
87+
qs = qs.prefetch_related(f.name)
88+
else:
89+
qs = self.model.objects.filter(pk=pk)
9890
if qs:
9991
return qs.first()
100-
else:
101-
return BaseApiResponse(message="Not Found", errno=404)
10292

10393
def _crud_get_objs_all(self, maximum: int = None, **filters: Any) -> Any:
10494
"""

tests/demo_app/controllers.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -110,8 +110,7 @@ async def must_be_super_user(self, word: str):
110110

111111
@http_get("/test_perm_only_super/", permissions=[BaseApiPermission])
112112
async def test_perm_only_super(self, request):
113-
response = await self.service.add_obj(title="test_event_title")
114-
event_id = response.json_data.get("data")["id"]
113+
event_id = await self.service.add_obj(title="test_event_title")
115114
# return await self.service.get_obj(id=note.id)
116115
return await sync_to_async(self.get_object_or_none)(Event, id=event_id)
117116

tests/demo_app/test_async_api_permissions.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ async def test_demo(self, easy_api_client):
2323
"/must_be_authenticated/?word=authenticated",
2424
content_type="application/json",
2525
)
26-
print(f"{response.__dict__.items()}")
2726
assert response.status_code == 200
2827
assert response.json().get("data")["says"] == "authenticated"
2928

@@ -187,7 +186,7 @@ async def test_perm_auto_apis_patch(self, transactional_db, easy_api_client):
187186
response = await client.patch(
188187
f"/{event.id}", json=new_data, content_type="application/json"
189188
)
190-
assert response.json().get("data")["pk"] == event.id
189+
assert response.json().get("data")
191190

192191
response = await client.get(
193192
f"/{event.id}",

tests/demo_app/test_async_auto_crud_apis.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -192,14 +192,14 @@ async def test_crud_default_patch(self, transactional_db, easy_api_client):
192192
)
193193

194194
assert response.status_code == 200
195-
assert response.json()["code"] == 404
195+
assert response.json()["code"] == 400
196196

197197
response = await client.patch(
198198
f"/{event.pk}", json=new_data, content_type="application/json"
199199
)
200200

201201
assert response.status_code == 200
202-
assert response.json().get("data")["pk"] == event.pk
202+
assert response.json().get("data")
203203

204204
response = await client.get(
205205
f"/{event.pk}",

0 commit comments

Comments
 (0)