2
2
import datetime
3
3
import decimal
4
4
import uuid
5
- from typing import TypeVar , Generic , Type , Any , Generator , List , Optional , Callable
5
+ from typing import (
6
+ TypeVar ,
7
+ Generic ,
8
+ Type ,
9
+ Any ,
10
+ Generator ,
11
+ List ,
12
+ Optional ,
13
+ Callable ,
14
+ Mapping ,
15
+ )
6
16
7
17
from django .core import validators # type: ignore[import-untyped]
8
18
from django .db import models # type: ignore[import-untyped]
50
60
}
51
61
52
62
try :
53
- from enumfields import EnumField
63
+ from enumfields import EnumField # type: ignore[import-untyped]
54
64
except ImportError :
55
65
EnumField = None
56
66
@@ -73,7 +83,7 @@ class DjangoDTOConfig(DTOConfig):
73
83
74
84
class DjangoModelDTO (AbstractDTO [T ], Generic [T ]):
75
85
attribute_accessor = _get_model_attribute
76
- custom_field_types : dict [type [AnyField ], Any ] | None = None
86
+ custom_field_types : Optional [ dict [type [AnyField ], Any ]] = None
77
87
78
88
@classmethod
79
89
def get_field_type (cls , field : Field , type_map : dict [type [AnyField ], Any ]) -> Any :
@@ -98,19 +108,26 @@ def get_field_constraints(cls, field: AnyField) -> KwargDefinition:
98
108
# add choices as enum. if field is an enum type, we hand this off to
99
109
# Litestar for native enum support
100
110
if field .choices and not (EnumField and isinstance (field , EnumField )):
101
- constraints ["enum" ] = [c [0 ] for c in field .choices ]
111
+ choices = field .choices
112
+ if isinstance (choices , Mapping ):
113
+ constraints ["enum" ] = list (choices .keys ())
114
+ else :
115
+ constraints ["enum" ] = [c [0 ] for c in choices ]
102
116
103
117
for validator in field .validators :
104
118
# fast path for known supported validators
105
- if isinstance (validator , validators .MinValueValidator ):
106
- constraints ["gt" ] = validator .limit_value
107
- elif isinstance (validator , validators .MinLengthValidator ):
108
- constraints ["min_length" ] = validator .limit_value
109
- elif isinstance (validator , validators .MaxValueValidator ):
110
- constraints ["lt" ] = validator .limit_value
111
- elif isinstance (validator , validators .MaxLengthValidator ):
112
- constraints ["max_length" ] = validator .limit_value
113
- elif isinstance (validator , validators .RegexValidator ):
119
+ # nullable fields do not support these constraints and for enum the
120
+ # constraint is defined implicitly by its values
121
+ if not field .null and "enum" not in constraints :
122
+ if isinstance (validator , validators .MinValueValidator ):
123
+ constraints ["gt" ] = validator .limit_value
124
+ elif isinstance (validator , validators .MinLengthValidator ):
125
+ constraints ["min_length" ] = validator .limit_value
126
+ elif isinstance (validator , validators .MaxValueValidator ):
127
+ constraints ["lt" ] = validator .limit_value
128
+ elif isinstance (validator , validators .MaxLengthValidator ):
129
+ constraints ["max_length" ] = validator .limit_value
130
+ if isinstance (validator , validators .RegexValidator ):
114
131
if validator .inverse_match :
115
132
if (
116
133
isinstance (cls .config , DjangoDTOConfig )
@@ -151,7 +168,7 @@ def create_constraints_for_validator(
151
168
@classmethod
152
169
def get_field_default (
153
170
cls , field : AnyField
154
- ) -> tuple [Any , Callable [..., Any ] | None ]:
171
+ ) -> tuple [Any , Optional [ Callable [..., Any ]] ]:
155
172
if isinstance (field , ForeignObjectRel ):
156
173
if isinstance (field , ManyToOneRel ):
157
174
return Empty , list
0 commit comments