22import logging
33import uuid
44from abc import ABCMeta
5- from typing import Any , Optional , Tuple , Type , Union
5+ from typing import Any , List , Optional , Tuple , Type , Union
66
77from django .db import models
88from django .http import HttpRequest
@@ -27,6 +27,10 @@ def __init__(self, service=None): # type: ignore
2727 self .service = service
2828 super ().__init__ (model = self .model )
2929
30+ # Critical to set Meta
31+ if hasattr (self , "Meta" ):
32+ self .model .Meta = self .Meta # type: ignore
33+
3034 # Define Controller APIs for auto generation
3135 async def get_obj (self , request : HttpRequest , id : int ) -> Any :
3236 """
@@ -65,24 +69,6 @@ async def get_objs(
6569 return await self .service .get_objs (maximum , ** json .loads (filters ))
6670 return await self .service .get_objs (maximum )
6771
68- @paginate
69- async def filter_objs (
70- self , request : HttpRequest , filters : Union [str , bytes ]
71- ) -> Any :
72- """
73- GET /filter/?filters={filters_dict}
74- Filter Objects with Django-ORM filter dict
75- """
76- return await self .service .filter_objs (** json .loads (filters ))
77-
78- @paginate
79- async def filter_exclude_objs (self , filters : Union [str , bytes ]) -> Any :
80- """
81- GET /filter_exclude/?filters={filters_dict}
82- Filter exclude Objects with Django-ORM filter dict
83- """
84- return await self .service .filter_exclude_objs (** json .loads (filters ))
85-
8672 # async def bulk_create_objs(self, request):
8773 # """
8874 # POST /bulk_create
@@ -101,15 +87,18 @@ async def filter_exclude_objs(self, filters: Union[str, bytes]) -> Any:
10187class CrudApiMetaclass (ABCMeta ):
10288 def __new__ (mcs , name : str , bases : Tuple [Type [Any ], ...], attrs : dict ) -> Any :
10389 # Get configs from Meta
104- temp_base : Type = type .__new__ (type , "object" , (), {})
10590 temp_cls : Type = super (CrudApiMetaclass , mcs ).__new__ (
106- mcs , name , (temp_base ,), attrs
91+ mcs , name , (object ,), attrs
10792 )
10893 temp_opts : ModelOptions = ModelOptions (getattr (temp_cls , "Meta" , None ))
94+ opts_model : Optional [Type [models .Model ]] = temp_opts .model
10995 opts_fields_exclude : Optional [str ] = temp_opts .model_exclude
11096 opts_fields : Optional [str ] = temp_opts .model_fields
111- opts_model : Optional [Type [models .Model ]] = temp_opts .model
11297 opts_recursive : Optional [bool ] = temp_opts .model_recursive
98+ opts_join : Optional [bool ] = temp_opts .model_join
99+ opts_sensitive_fields : Optional [
100+ Union [str , List [str ]]
101+ ] = temp_opts .sensitive_fields
113102
114103 base_cls_attrs = {
115104 "get_obj" : http_get ("/{id}" , summary = "Get a single object" )(
@@ -121,14 +110,6 @@ def __new__(mcs, name: str, bases: Tuple[Type[Any], ...], attrs: dict) -> Any:
121110 "get_all" : http_get ("/" , summary = "Get multiple objects" )(
122111 copy_func (CrudAPI .get_objs ) # type: ignore
123112 ),
124- "filter_objs" : http_get ("/filter/" , summary = "Filter" )(
125- copy_func (CrudAPI .filter_objs ) # type: ignore
126- ),
127- "filter_exclude_objs" : http_get (
128- "/filter_exclude/" , summary = "Filter exclude"
129- )(
130- copy_func (CrudAPI .filter_exclude_objs ) # type: ignore
131- ),
132113 }
133114
134115 if opts_model :
@@ -143,7 +124,6 @@ class Config:
143124 model_fields = "__all__"
144125 else :
145126 model_fields = opts_fields if opts_fields else "__all__"
146- model_recursive = opts_recursive
147127
148128 async def add_obj ( # type: ignore
149129 self , request : HttpRequest , data : DataSchema
@@ -163,7 +143,7 @@ async def patch_obj( # type: ignore
163143 ) -> Any :
164144 """
165145 PATCH /{id}
166- Update a single field for a Object
146+ Update a single object
167147 """
168148 if await self .service .patch_obj (id = id , payload = data .dict ()):
169149 return BaseApiResponse ("Updated." )
@@ -195,21 +175,35 @@ async def patch_obj( # type: ignore
195175 mcs , name , (new_base ,), attrs
196176 )
197177
198- new_cls .model = opts_model
199- new_cls .model_exclude = opts_fields_exclude
200- new_cls .model_fields = opts_fields
201- new_cls .model_recursive = opts_recursive
202-
178+ if opts_model :
179+ setattr (opts_model .Meta , "model_exclude" , opts_fields_exclude )
180+ setattr (opts_model .Meta , "model_fields" , opts_fields )
181+ setattr (opts_model .Meta , "model_recursive" , opts_recursive )
182+ setattr (opts_model .Meta , "model_join" , opts_join )
183+ setattr (opts_model .Meta , "sensitive_fields" , opts_sensitive_fields )
184+ setattr (new_cls , "model" , opts_model )
203185 return new_cls
204186
205187
206188class ModelOptions :
207189 def __init__ (self , options : object = None ):
190+ """
191+ Configuration:
192+ model: django model
193+ model_fields: fields to be included in Schema, default to "__all__"
194+ model_exclude: fields to be excluded in Schema
195+ model_join: retrieve all m2m/FK fields, default to True
196+ model_recursive: recursively retrieve FK models, default to False
197+ """
208198 self .model : Optional [Type [models .Model ]] = getattr (options , "model" , None )
209199 self .model_fields : Optional [Union [str ]] = getattr (options , "model_fields" , None )
210200 self .model_exclude : Optional [Union [str ]] = getattr (
211201 options , "model_exclude" , None
212202 )
203+ self .model_join : Optional [Union [bool ]] = getattr (options , "model_join" , True )
213204 self .model_recursive : Optional [Union [bool ]] = getattr (
214205 options , "model_recursive" , False
215206 )
207+ self .sensitive_fields : Optional [Union [str , List [str ]]] = getattr (
208+ options , "sensitive_fields" , ["token" , "password" ]
209+ )
0 commit comments