11from bson import ObjectId , errors
2- from bson .errors import InvalidId
32from django .core import exceptions
43from django .db .models .fields import Field
54from django .utils .translation import gettext_lazy as _
@@ -14,33 +13,44 @@ class ObjectIdMixin:
1413 def db_type (self , connection ):
1514 return "objectId"
1615
16+ def get_prep_value (self , value ):
17+ if value is None :
18+ return None
19+ # Accept int for compatibility with Django's test suite which has many
20+ # instances of manually assigned integer IDs, as well as for things
21+ # like settings.SITE_ID which has a system check requiring an integer.
22+ if isinstance (value , (ObjectId | int )):
23+ return value
24+ try :
25+ return ObjectId (value )
26+ except (errors .InvalidId , TypeError ) as e :
27+ # A manually assigned integer ID?
28+ if isinstance (value , str ) and value .isdigit ():
29+ return int (value )
30+ raise ValueError (f"Field '{ self .name } ' expected an ObjectId but got { value !r} ." ) from e
31+
1732 def rel_db_type (self , connection ):
1833 return "objectId"
1934
20-
21- class ObjectIdField (ObjectIdMixin , Field ):
22- def get_internal_type (self ):
23- return "ObjectIdField"
24-
2535 def to_python (self , value ):
26- if value is None :
36+ if value is None or isinstance ( value , int ) :
2737 return value
2838 try :
2939 return ObjectId (value )
30- except (TypeError , InvalidId ):
31- raise exceptions .ValidationError (
32- self .error_messages ["invalid" ],
33- code = "invalid" ,
34- params = {"value" : value },
35- ) from None
40+ except (errors .InvalidId , TypeError ):
41+ try :
42+ return int (value )
43+ except (ValueError , TypeError ):
44+ raise exceptions .ValidationError (
45+ self .error_messages ["invalid" ],
46+ code = "invalid" ,
47+ params = {"value" : value },
48+ ) from None
3649
37- def get_prep_value (self , value ):
38- if value is None :
39- return None
40- try :
41- return ObjectId (value )
42- except (errors .InvalidId , TypeError ) as e :
43- raise ValueError (f"Field '{ self .name } ' expected an ObjectId but got { value !r} ." ) from e
50+
51+ class ObjectIdField (ObjectIdMixin , Field ):
52+ def get_internal_type (self ):
53+ return "ObjectIdField"
4454
4555 def deconstruct (self ):
4656 name , path , args , kwargs = super ().deconstruct ()
0 commit comments