66from core .const .tag import OpenAPITag
77from core .models import MarkdownField
88from core .serializer .json_schema_serializer import JsonSchemaSerializer
9- from django .db .models .base import Model
109from django .db .models .fields import TextField
1110from django .db .models .fields .files import FileField
1211from django .db .models .fields .related import ForeignKey , ManyToManyField
12+ from django .db .models .query import QuerySet
1313from drf_spectacular import openapi , types , utils
1414from modeltranslation .fields import TranslationField
15- from rest_framework import decorators , response , status , viewsets
15+ from rest_framework import decorators , response , serializers , status , viewsets
1616
1717
1818class JsonSchemaViewSet (viewsets .GenericViewSet ):
@@ -24,18 +24,17 @@ def __new__(cls, *args: tuple, **kwargs: dict) -> JsonSchemaViewSet:
2424
2525 @staticmethod
2626 @functools .lru_cache
27- def get_enum_values (model : Model , is_nullable : bool ) -> list [dict [str , str ]]:
27+ def get_enum_values (model_qs : QuerySet , is_nullable : bool ) -> list [dict [str , str ]]:
2828 enum_values : list [dict [str , str ]] = [{"const" : None , "title" : "빈 값" }] if is_nullable else []
2929
30- if hasattr (model , "objects" ):
31- qs = model .objects .all ()
32- if hasattr (qs , "filter_active" ):
33- qs = qs .filter_active ()
34- elif hasattr (model , "is_active" ):
35- qs = qs .filter (is_active = True )
30+ qs = model_qs .all ()
31+ if hasattr (qs , "filter_active" ):
32+ qs = qs .filter_active ()
33+ elif hasattr (model_qs .model , "is_active" ):
34+ qs = qs .filter (is_active = True )
3635
37- for row in qs :
38- enum_values .append ({"const" : str (row .pk ), "title" : str (row )})
36+ for row in qs :
37+ enum_values .append ({"const" : str (row .pk ), "title" : str (row )})
3938
4039 return enum_values
4140
@@ -60,18 +59,23 @@ def get_json_schema(self) -> dict:
6059 schema_field .pop ("pattern" , None )
6160
6261 if hasattr (serializer_class .Meta , "model" ) and "properties" in result ["schema" ]:
62+ ser_fields : dict [str , serializers .Field ] = serializer_class ().fields
6363 model_fields = serializer_class .Meta .model ._meta .fields
6464 model_m2m_fields = serializer_class .Meta .model ._meta .many_to_many
6565
6666 for field in model_fields + model_m2m_fields :
67- if field .name not in result ["schema" ]["properties" ]:
67+ if field .name not in result ["schema" ]["properties" ] or field . name not in ser_fields :
6868 continue
6969
7070 if isinstance (field , ForeignKey ):
71- e_values = self .get_enum_values (field .related_model , field .null )
71+ if not (s_field := typing .cast (serializers .PrimaryKeyRelatedField | None , ser_fields [field .name ])):
72+ continue
73+ e_values = self .get_enum_values (s_field .get_queryset (), field .null )
7274 result ["schema" ]["properties" ][field .name ]["oneOf" ] = e_values
7375 elif isinstance (field , ManyToManyField ):
74- e_values = self .get_enum_values (field .related_model , False )
76+ if not (s_field := typing .cast (serializers .ManyRelatedField | None , ser_fields [field .name ])):
77+ continue
78+ e_values = self .get_enum_values (s_field .child_relation .get_queryset (), False )
7579 result ["schema" ]["properties" ][field .name ]["items" ]["oneOf" ] = e_values
7680 result ["schema" ]["properties" ][field .name ]["uniqueItems" ] = True
7781 self .set_ui_schema (result ["ui_schema" ], field .name , {"ui:field" : "m2m_select" })
0 commit comments