Skip to content

Commit 998dc63

Browse files
committed
fix: JSONSchema enum 선택 가능 값이 필드 쿼리셋을 벗어나는 문제 수정
1 parent 423a207 commit 998dc63

File tree

1 file changed

+18
-14
lines changed

1 file changed

+18
-14
lines changed

app/core/viewset/json_schema_viewset.py

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,13 @@
66
from core.const.tag import OpenAPITag
77
from core.models import MarkdownField
88
from core.serializer.json_schema_serializer import JsonSchemaSerializer
9-
from django.db.models.base import Model
109
from django.db.models.fields import TextField
1110
from django.db.models.fields.files import FileField
1211
from django.db.models.fields.related import ForeignKey, ManyToManyField
12+
from django.db.models.query import QuerySet
1313
from drf_spectacular import openapi, types, utils
1414
from 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

1818
class 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

Comments
 (0)