6
6
from pydantic import BaseModel as PydanticModel
7
7
8
8
from ninja_extra .exceptions import NotFound
9
- from ninja_extra .shortcuts import get_object_or_exception
9
+ from ninja_extra .shortcuts import aget_object_or_exception , get_object_or_exception
10
10
11
11
from .interfaces import AsyncModelServiceBase , ModelServiceBase
12
12
@@ -21,21 +21,17 @@ class ModelService(ModelServiceBase, AsyncModelServiceBase):
21
21
def __init__ (self , model : t .Type [Model ]) -> None :
22
22
self .model = model
23
23
24
+ # --- Synchonous Methods ---
25
+
24
26
def get_one (self , pk : t .Any , ** kwargs : t .Any ) -> t .Any :
25
27
obj = get_object_or_exception (
26
28
klass = self .model , error_message = None , exception = NotFound , pk = pk
27
29
)
28
30
return obj
29
31
30
- async def get_one_async (self , pk : t .Any , ** kwargs : t .Any ) -> t .Any :
31
- return await sync_to_async (self .get_one , thread_sensitive = True )(pk , ** kwargs )
32
-
33
32
def get_all (self , ** kwargs : t .Any ) -> t .Union [QuerySet , t .List [t .Any ]]:
34
33
return self .model .objects .all ()
35
34
36
- async def get_all_async (self , ** kwargs : t .Any ) -> t .Union [QuerySet , t .List [t .Any ]]:
37
- return await sync_to_async (self .get_all , thread_sensitive = True )(** kwargs )
38
-
39
35
def create (self , schema : PydanticModel , ** kwargs : t .Any ) -> t .Any :
40
36
data = schema .model_dump (by_alias = True )
41
37
data .update (kwargs )
@@ -63,9 +59,6 @@ def create(self, schema: PydanticModel, **kwargs: t.Any) -> t.Any:
63
59
)
64
60
raise TypeError (msg ) from tex
65
61
66
- async def create_async (self , schema : PydanticModel , ** kwargs : t .Any ) -> t .Any :
67
- return await sync_to_async (self .create , thread_sensitive = True )(schema , ** kwargs )
68
-
69
62
def update (self , instance : Model , schema : PydanticModel , ** kwargs : t .Any ) -> t .Any :
70
63
data = schema .model_dump (exclude_none = True )
71
64
data .update (kwargs )
@@ -74,23 +67,64 @@ def update(self, instance: Model, schema: PydanticModel, **kwargs: t.Any) -> t.A
74
67
instance .save ()
75
68
return instance
76
69
70
+ def patch (self , instance : Model , schema : PydanticModel , ** kwargs : t .Any ) -> t .Any :
71
+ return self .update (instance = instance , schema = schema , ** kwargs )
72
+
73
+ def delete (self , instance : Model , ** kwargs : t .Any ) -> t .Any :
74
+ instance .delete ()
75
+
76
+ # --- Asynchronous Methods (using native async ORM where possible) ---
77
+
78
+ async def get_one_async (self , pk : t .Any , ** kwargs : t .Any ) -> t .Any :
79
+ obj = await aget_object_or_exception (
80
+ klass = self .model , error_message = None , exception = NotFound , pk = pk
81
+ )
82
+ return obj
83
+
84
+ async def get_all_async (self , ** kwargs : t .Any ) -> t .Union [QuerySet , t .List [t .Any ]]:
85
+ return await sync_to_async (self .get_all , thread_sensitive = True )(** kwargs )
86
+
87
+ async def create_async (self , schema : PydanticModel , ** kwargs : t .Any ) -> t .Any :
88
+ data = schema .model_dump (by_alias = True )
89
+ data .update (kwargs )
90
+
91
+ try :
92
+ instance = await self .model ._default_manager .acreate (** data )
93
+ return instance
94
+ except TypeError as tex : # pragma: no cover
95
+ tb = traceback .format_exc ()
96
+ msg = (
97
+ "Got a `TypeError` when calling `%s.%s.create()`. "
98
+ "This may be because you have a writable field on the "
99
+ "serializer class that is not a valid argument to "
100
+ "`%s.%s.create()`. You may need to make the field "
101
+ "read-only, or override the %s.create() method to handle "
102
+ "this correctly.\n Original exception was:\n %s"
103
+ % (
104
+ self .model .__name__ ,
105
+ self .model ._default_manager .name ,
106
+ self .model .__name__ ,
107
+ self .model ._default_manager .name ,
108
+ self .__class__ .__name__ ,
109
+ tb ,
110
+ )
111
+ )
112
+ raise TypeError (msg ) from tex
113
+
77
114
async def update_async (
78
115
self , instance : Model , schema : PydanticModel , ** kwargs : t .Any
79
116
) -> t .Any :
80
- return await sync_to_async ( self . update , thread_sensitive = True )(
81
- instance , schema , ** kwargs
82
- )
83
-
84
- def patch ( self , instance : Model , schema : PydanticModel , ** kwargs : t . Any ) -> t . Any :
85
- return self . update ( instance = instance , schema = schema , ** kwargs )
117
+ data = schema . model_dump ( exclude_none = True )
118
+ data . update ( kwargs )
119
+ for attr , value in data . items ():
120
+ setattr ( instance , attr , value )
121
+ await instance . asave ()
122
+ return instance
86
123
87
124
async def patch_async (
88
125
self , instance : Model , schema : PydanticModel , ** kwargs : t .Any
89
126
) -> t .Any :
90
127
return await self .update_async (instance = instance , schema = schema , ** kwargs )
91
128
92
- def delete (self , instance : Model , ** kwargs : t .Any ) -> t .Any :
93
- instance .delete ()
94
-
95
129
async def delete_async (self , instance : Model , ** kwargs : t .Any ) -> t .Any :
96
- return await sync_to_async ( self . delete , thread_sensitive = True )( instance )
130
+ await instance . adelete ( )
0 commit comments