Skip to content

Commit eea98d7

Browse files
committed
atomic update objects
1 parent fe2d709 commit eea98d7

File tree

3 files changed

+100
-3
lines changed

3 files changed

+100
-3
lines changed

fastapi_jsonapi/atomic/atomic.py

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
OperationRelationshipSchema,
2121
)
2222
from fastapi_jsonapi.utils.dependency_helper import DependencyHelper
23+
from fastapi_jsonapi.views.detail_view import DetailViewBase
2324
from fastapi_jsonapi.views.list_view import ListViewBase
2425
from fastapi_jsonapi.views.utils import HTTPMethodConfig
2526
from fastapi_jsonapi.views.view_base import ViewBase
@@ -105,6 +106,8 @@ async def view_atomic(
105106

106107
results = []
107108

109+
# TODO: try/except, catch schema ValidationError
110+
108111
previous_dl: Optional["BaseDataLayer"] = None
109112
for operation in prepared_operations:
110113
dl = operation.data_layer
@@ -118,8 +121,16 @@ async def view_atomic(
118121
# response.data.id
119122
results.append({"data": response.data})
120123
elif operation.action == "update":
121-
# TODO
122124
data = operation.jsonapi.schema_in_patch(data=operation.data)
125+
assert isinstance(operation.view, DetailViewBase)
126+
view: "DetailViewBase" = operation.view
127+
response = await view.process_update_object(
128+
dl=dl,
129+
obj_id=data.data.id,
130+
data_update=data.data,
131+
)
132+
# response.data.id
133+
results.append({"data": response.data})
123134
elif operation.action == "remove":
124135
pass
125136
else:

fastapi_jsonapi/views/detail_view.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,13 +48,20 @@ async def handle_update_resource(
4848
data_update: BaseJSONAPIItemInSchema,
4949
**extra_view_deps,
5050
) -> JSONAPIResultDetailSchema:
51+
dl: "BaseDataLayer" = await self.get_data_layer(extra_view_deps)
52+
return await self.process_update_object(dl=dl, obj_id=obj_id, data_update=data_update)
53+
54+
async def process_update_object(
55+
self,
56+
dl: "BaseDataLayer",
57+
obj_id: str,
58+
data_update: BaseJSONAPIItemInSchema,
59+
):
5160
if obj_id != data_update.id:
5261
raise BadRequest(
5362
detail="obj_id and data.id should be same",
5463
pointer="/data/id",
5564
)
56-
dl: "BaseDataLayer" = await self.get_data_layer(extra_view_deps)
57-
5865
view_kwargs = {dl.url_id_field: obj_id}
5966
db_object = await dl.get_object(view_kwargs=view_kwargs, qs=self.query_params)
6067

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
import logging
2+
3+
from httpx import AsyncClient
4+
from pytest import mark # noqa
5+
from sqlalchemy.ext.asyncio import AsyncSession
6+
from starlette import status
7+
8+
from tests.misc.utils import fake
9+
from tests.models import User, UserBio
10+
from tests.schemas import UserAttributesBaseSchema, UserBioBaseSchema
11+
12+
pytestmark = mark.asyncio
13+
14+
logging.basicConfig(level=logging.DEBUG)
15+
16+
17+
class TestAtomicUpdateObjects:
18+
async def test_update_two_objects(
19+
self,
20+
client: AsyncClient,
21+
async_session: AsyncSession,
22+
user_1: User,
23+
user_1_bio: UserBio,
24+
):
25+
user_data = UserAttributesBaseSchema.from_orm(user_1)
26+
user_bio_data = UserBioBaseSchema.from_orm(user_1_bio)
27+
user_data.name = fake.name()
28+
user_bio_data.favourite_movies = fake.sentence()
29+
assert user_1.name != user_data.name
30+
assert user_1_bio.favourite_movies != user_bio_data.favourite_movies
31+
data_atomic_request = {
32+
"atomic:operations": [
33+
{
34+
"op": "update",
35+
"data": {
36+
"id": str(user_1.id),
37+
"type": "user",
38+
"attributes": user_data.dict(),
39+
},
40+
},
41+
{
42+
"op": "update",
43+
"data": {
44+
"id": str(user_1_bio.id),
45+
"type": "user_bio",
46+
"attributes": user_bio_data.dict(),
47+
},
48+
},
49+
],
50+
}
51+
response = await client.post("/operations", json=data_atomic_request)
52+
assert response.status_code == status.HTTP_200_OK, response.text
53+
response_data = response.json()
54+
assert "atomic:results" in response_data, response_data
55+
results = response_data["atomic:results"]
56+
assert results
57+
await async_session.refresh(user_1)
58+
await async_session.refresh(user_1_bio)
59+
assert user_1.name == user_data.name
60+
assert user_1_bio.favourite_movies == user_bio_data.favourite_movies
61+
62+
assert results == [
63+
{
64+
"data": {
65+
"attributes": user_data.dict(),
66+
"id": str(user_1.id),
67+
"type": "user",
68+
},
69+
"meta": None,
70+
},
71+
{
72+
"data": {
73+
"attributes": user_bio_data.dict(),
74+
"id": str(user_1_bio.id),
75+
"type": "user_bio",
76+
},
77+
"meta": None,
78+
},
79+
]

0 commit comments

Comments
 (0)