Skip to content

Commit 969eba7

Browse files
authored
Merge pull request #1 from freemindcore/feat/serizalize_qs_m2m
Feat/serizalize qs m2m
2 parents 6d257d0 + 74154ae commit 969eba7

File tree

5 files changed

+48
-9
lines changed

5 files changed

+48
-9
lines changed

easy/domain/orm.py

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import logging
2-
from typing import Any, Tuple, Type
2+
from typing import Any, Dict, List, Tuple, Type
33

44
from django.db import models
55
from django.db.models.query import QuerySet
@@ -14,8 +14,13 @@
1414
class CrudModel(object):
1515
def __init__(self, model: Type[models.Model]):
1616
self.model = model
17+
self.m2m_fields = [
18+
f
19+
for f in self.model._meta.get_fields(include_hidden=True)
20+
if isinstance(f, models.ManyToManyField)
21+
]
1722

18-
def __get_fields(self, payload: dict) -> Tuple[dict, dict]:
23+
def __get_fields(self, payload: Dict) -> Tuple[Dict, Dict]:
1924
m2m_fields = {}
2025
local_fields = {}
2126
for field in payload.keys():
@@ -27,12 +32,12 @@ def __get_fields(self, payload: dict) -> Tuple[dict, dict]:
2732
return local_fields, m2m_fields
2833

2934
# Define BASE CRUD
30-
def _crud_add_obj(self, **payload: dict) -> Any:
35+
def _crud_add_obj(self, **payload: Dict) -> Any:
3136
local_fields, m2m_fields = self.__get_fields(payload)
3237
obj = self.model.objects.create(**local_fields)
3338
if m2m_fields:
3439
for field, value in m2m_fields.items():
35-
if value and isinstance(value, list):
40+
if value and isinstance(value, List):
3641
m2m_f = getattr(obj, field)
3742
m2m_f.set(value)
3843
return obj
@@ -47,7 +52,7 @@ def _crud_del_obj(self, id: int) -> "BaseApiResponse":
4752
{"Detail": "Not found."}, message="Not found."
4853
) # pragma: no cover
4954

50-
def _crud_update_obj(self, id: int, payload: dict) -> "BaseApiResponse":
55+
def _crud_update_obj(self, id: int, payload: Dict) -> "BaseApiResponse":
5156
local_fields, m2m_fields = self.__get_fields(payload)
5257
try:
5358
obj, created = self.model.objects.update_or_create(
@@ -64,7 +69,17 @@ def _crud_update_obj(self, id: int, payload: dict) -> "BaseApiResponse":
6469
return BaseApiResponse({"id": obj.id, "created": created})
6570

6671
def _crud_get_obj(self, id: int) -> Any:
67-
return get_object_or_none(self.model, id=id)
72+
if self.m2m_fields:
73+
qs = self.model.objects.filter(id=id).prefetch_related(
74+
self.m2m_fields[0].name
75+
)
76+
for f in self.m2m_fields[1:]:
77+
qs = qs.prefetch_related(f.name)
78+
else:
79+
qs = self.model.objects.filter(id=id)
80+
if qs:
81+
return qs.first()
82+
return BaseApiResponse()
6883

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

easy/domain/serializers.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,6 @@ def serialize_model_instance(
4646
"""Serializes Django model instance to dictionary"""
4747
out = {}
4848
for field in obj._meta.get_fields():
49-
# TODO: Add OneToOne relationship??
5049
if is_one_relationship(field):
5150
out.update(serialize_foreign_key(obj, field, referrers + (obj,)))
5251

tests/demo_app/controllers.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,10 +68,13 @@ async def get_objs_list_with_filter_exclude(self, request):
6868

6969
@http_get(
7070
"/qs",
71-
response=List[EventSchema],
7271
)
7372
async def list_events(self):
74-
return await sync_to_async(list)(self.model.objects.all())
73+
qs = await sync_to_async(self.model.objects.all)()
74+
await sync_to_async(list)(qs)
75+
if qs:
76+
return qs
77+
return BaseApiResponse()
7578

7679

7780
@api_controller("unittest")

tests/demo_app/models.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,10 @@ class Event(TestBaseModel):
3535

3636
owner = models.ManyToManyField(to=Client, related_name="events", null=True)
3737

38+
lead_owner = models.ManyToManyField(to=Client, related_name="lead_owner", null=True)
39+
40+
boss_owner = models.ManyToManyField(to=Client, related_name="boss_owner", null=True)
41+
3842
type = models.ForeignKey(Type, on_delete=models.CASCADE, null=True)
3943

4044
def __str__(self):

tests/demo_app/test_async_other_apis.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,3 +99,21 @@ async def test_qs_list(self, transactional_db, easy_api_client):
9999
== data[4]["title"]
100100
== "AsyncAPIEvent_create_qs_list_88"
101101
)
102+
103+
async def test_qs_(self, transactional_db, easy_api_client):
104+
client = easy_api_client(EasyCrudAPIController)
105+
106+
for i in range(4):
107+
type = await sync_to_async(Type.objects.create)(name=f"Test-Type-{i}")
108+
object_data = await EventService.prepare_create_event_data(dummy_data)
109+
object_data.update(title=f"{object_data['title']}_qs_{i}", type=type.id)
110+
await client.put("/", json=object_data)
111+
112+
response = await client.get(
113+
"/qs",
114+
)
115+
assert response.status_code == 200
116+
117+
data = response.json().get("data")
118+
119+
assert data[0]["title"] == "AsyncAPIEvent_create_qs_0"

0 commit comments

Comments
 (0)