2323from django .db .utils import IntegrityError as DBIntegrityError
2424
2525from ..exceptions import (
26- ADRException ,
2726 IntegrityError ,
27+ InvalidFieldError ,
2828 MultipleObjectsReturnedError ,
2929 ObjectDoesNotExistError ,
3030 ObjectNotSavedError ,
@@ -44,7 +44,9 @@ def wrapper(*args, **kwargs):
4444 try :
4545 return func (* args , ** kwargs )
4646 except (FieldError , FieldDoesNotExist , ValidationError , DataError ) as e :
47- raise ADRException (extra_detail = f"One or more fields set or accessed are invalid: { e } " )
47+ raise InvalidFieldError (
48+ extra_detail = f"One or more fields set or accessed are invalid: { e } "
49+ )
4850
4951 return wrapper
5052
@@ -75,13 +77,11 @@ def __new__(
7577 if parents :
7678 # dynamically make the properties listed into class attrs
7779 if "_properties" in namespace :
78- dynamic_props_field = namespace ["_properties" ]
79- if hasattr (dynamic_props_field , "default" ):
80- props = dynamic_props_field .default
81- new_namespace = {** namespace }
82- for prop in props :
83- new_namespace [prop ] = None
84- new_cls = super_new (mcs , cls_name , bases , new_namespace , ** kwargs )
80+ props = namespace ["_properties" ]
81+ new_namespace = {** namespace }
82+ for prop in props :
83+ new_namespace [prop ] = None
84+ new_cls = super_new (mcs , cls_name , bases , new_namespace , ** kwargs )
8585 # save every class extending BaseModel
8686 mcs ._cls_registry [cls_name ] = new_cls
8787 # add exceptions
@@ -266,7 +266,7 @@ def _orm_db(self) -> str:
266266 def db (self ):
267267 return self ._orm_db
268268
269- def as_dict (self ) :
269+ def as_dict (self , recursive = False ) -> dict [ str , Any ] :
270270 out_dict = {}
271271 # use a combination of vars and fields
272272 cls_fields = set (self ._get_field_names () + self ._get_var_field_names ())
@@ -276,6 +276,9 @@ def as_dict(self):
276276 value = getattr (self , field_ , None )
277277 if value is None : # skip and use defaults
278278 continue
279+ if isinstance (value , list ) and recursive :
280+ # convert to guids
281+ value = [obj .guid for obj in value ]
279282 out_dict [field_ ] = value
280283 return out_dict
281284
@@ -293,7 +296,14 @@ def _prepare_for_save(self, **kwargs):
293296 continue
294297 if isinstance (value , list ):
295298 objs = [obj ._orm_instance for obj in value ]
296- getattr (self ._orm_instance , field_ ).add (* objs )
299+ try :
300+ getattr (self ._orm_instance , field_ ).add (* objs )
301+ except (ObjectDoesNotExist , ValueError ) as e :
302+ if value :
303+ obj_cls = value [0 ].__class__
304+ raise obj_cls .NotSaved (extra_detail = str (e ))
305+ else :
306+ raise ValueError (str (e ))
297307 else :
298308 if isinstance (value , BaseModel ): # relations
299309 try :
@@ -340,7 +350,7 @@ def delete(self, **kwargs):
340350 def from_db (cls , orm_instance , parent = None ):
341351 cls_fields = dict (cls ._get_field_names (with_types = True , include_private = True ))
342352 model_fields = cls ._get_orm_field_names (orm_instance )
343- obj = cls ()
353+ obj = cls . __new__ ( cls ) # Bypass __init__ to skip validation
344354 for field_ in model_fields :
345355 if field_ in cls_fields :
346356 attr = field_
@@ -416,6 +426,11 @@ def create(cls, **kwargs):
416426 @classmethod
417427 @handle_field_errors
418428 def get (cls , ** kwargs ):
429+ """Get an object from the database using the ORM model."""
430+ # convert basemodel instances to orm instances
431+ for key , value in kwargs .items ():
432+ if isinstance (value , BaseModel ):
433+ kwargs [key ] = value ._orm_instance
419434 try :
420435 orm_instance = cls ._orm_model_cls .objects .using (kwargs .pop ("using" , "default" )).get (
421436 ** kwargs
@@ -429,39 +444,26 @@ def get(cls, **kwargs):
429444
430445 @classmethod
431446 @handle_field_errors
432- def get_or_create (cls , ** kwargs ):
433- try :
434- return cls .get (** kwargs ), False
435- except cls .DoesNotExist :
436- # Try to create an object using passed params.
437- try :
438- return cls .create (** kwargs ), True
439- except cls .IntegrityError :
440- try :
441- return cls .get (** kwargs ), False
442- except cls .DoesNotExist :
443- pass
444- raise
445-
446- @classmethod
447- @handle_field_errors
448- def filter (cls , ** kwargs ):
447+ def filter (cls , ** kwargs ) -> "ObjectSet" :
448+ for key , value in kwargs .items ():
449+ if isinstance (value , BaseModel ):
450+ kwargs [key ] = value ._orm_instance
449451 qs = cls ._orm_model_cls .objects .using (kwargs .pop ("using" , "default" )).filter (** kwargs )
450452 return ObjectSet (_model = cls , _orm_model = cls ._orm_model_cls , _orm_queryset = qs )
451453
452454 @classmethod
453455 @handle_field_errors
454- def find (cls , query = "" , ** kwargs ):
456+ def find (cls , query = "" , ** kwargs ) -> "ObjectSet" :
455457 qs = cls ._orm_model_cls .find (query = query , ** kwargs )
456458 return ObjectSet (_model = cls , _orm_model = cls ._orm_model_cls , _orm_queryset = qs )
457459
458- def get_tags (self ):
460+ def get_tags (self ) -> str :
459461 return self .tags
460462
461- def set_tags (self , tag_str ) :
463+ def set_tags (self , tag_str : str ) -> None :
462464 self .tags = tag_str
463465
464- def add_tag (self , tag , value = None ):
466+ def add_tag (self , tag : str , value : str | None = None ) -> None :
465467 self .rem_tag (tag )
466468 tags = shlex .split (self .get_tags ())
467469 if value :
@@ -470,14 +472,14 @@ def add_tag(self, tag, value=None):
470472 tags .append (tag )
471473 self ._rebuild_tags (tags )
472474
473- def rem_tag (self , tag ) :
475+ def rem_tag (self , tag : str ) -> None :
474476 tags = shlex .split (self .get_tags ())
475477 for t in tags :
476478 if t == tag or t .split ("=" )[0 ] == tag :
477479 tags .remove (t )
478480 self ._rebuild_tags (tags )
479481
480- def remove_tag (self , tag ) :
482+ def remove_tag (self , tag : str ) -> None :
481483 self .rem_tag (tag )
482484
483485
@@ -532,8 +534,8 @@ def delete(self):
532534
533535 def values_list (self , * fields , flat = False ):
534536 if flat and len (fields ) > 1 :
535- raise TypeError (
536- "'flat' is not valid when values_list is called with more than one " " field."
537+ raise ValueError (
538+ "'flat' is not valid when values_list is called with more than one field."
537539 )
538540 ret = []
539541 for obj in self ._obj_set :
@@ -555,11 +557,9 @@ def __get__(self, obj, obj_type=None):
555557 return getattr (obj , self ._name , self ._default )
556558
557559 def __set__ (self , obj , value ):
558- cleaned_value = None
559- if value is not None :
560- cleaned_value = self .process (value , obj )
560+ cleaned_value = self .process (value , obj )
561561 setattr (obj , self ._name , cleaned_value )
562562
563563 @abstractmethod
564564 def process (self , value , obj ):
565- pass
565+ pass # pragma: no cover
0 commit comments