Django REST Framework. вложенный сериализатор игнорирует мои данные
Через fetch передаю данные с одним файлом + заголовок + описание + еще один json (answers_set), которые необходимо так же сериализовать. Запрос получается следующий:
<QueryDict: {'title': ['dsasad'], 'description': ['dsadads'], 'content': ['<p>dsadas</p>'], 'answers_set': ['[{"title":"asddas"},{"title":"dsaasd"}]'], 'tags': ['dsasda'], 'blog': ['11'], 'preview': [<InMemoryUploadedFile: Django-авторизация.jpg (image/jpeg)>]}>
То есть, данные есть в answers_set, ничего не пропадает, сама вьюшка c классом:
class SurveyViewSet(viewsets.ModelViewSet):
queryset = Survey.objects.all()
serializer_class = SurveySerializer
permission_classes = [IsAuthenticated]
# parser_classes = [MultiPartParser, FormParser, JSONParser]
def get_serializer_class(self):
if self.action in ["add_view", "hide_survey", "show_survey"]:
return SurveyNoneSerializer
elif self.action == "send_scores_to_option":
return SurveyScoresSerializer
else:
return SurveySerializer
def get_queryset(self):
if self.action == 'send_scores_to_option':
return SurveyRadio.objects.all()
return super().get_queryset()
def custom_get_object(self, **params):
queryset = self.filter_queryset(self.get_queryset())
lookup_url_kwarg = self.lookup_url_kwarg or self.lookup_field
assert lookup_url_kwarg in self.kwargs, (
(self.__class__.__name__, lookup_url_kwarg)
)
filter_kwargs = {self.lookup_field: self.kwargs[lookup_url_kwarg]}
obj = get_object_or_404(queryset, **filter_kwargs, **params)
self.check_object_permissions(self.request, obj)
return obj
def create(self, request, *args, **kwargs):
_ = get_object_or_404(Blog, user=request.user.id, id=request.data.get("blog", False))
data = {}
if request.user.is_authenticated and request.user.is_published_post:
# _data = QueryDict.copy(request.data)
_data = request.data
print(_data)
_data["language"] = request.user.language
draft = DraftSurvey.objects.filter(
user=request.user.id, blog=_data["blog"]
)
if not _data.get("preview", False):
if draft and draft[0].preview:
_data["preview"] = draft[0].preview
serializer = SurveySerializer(data=_data, user=request.user)
if serializer.is_valid():
survey = serializer.save()
if draft:
draft[0].delete()
data["success"] = "Successful created a new survey."
data["slug"] = survey.slug
else:
data = serializer.errors
else:
data["ban"] = "You can't publish surveys."
print(data)
return Response(data)
Сериализаторы:
class AnswerSerializer(serializers.ModelSerializer):
id = serializers.IntegerField(required=False)
class Meta:
model = SurveyRadio
fields = [
"id",
"title",
]
class SurveySerializer(serializers.ModelSerializer):
tags = serializers.CharField(required=False, write_only=True)
answers_set = AnswerSerializer(source="answers", many=True)
class Meta:
model = Survey
fields = [
"preview",
"title",
"description",
"content",
"language",
"tags",
"blog",
"answers_set",
"level_access",
]
На выходе же я получаю следующую ошибку :
{'answers_set': [ErrorDetail(string='This field is required.', code='required')]}
Ответы (1 шт):
Кажется дело в том, что answers_set это не json. ТО есть не список объектов answers, а строка, содержащаяя json со списком объектов.
Вы можете исправить это внутри fetch'a. (Т.к. вы не предоставили его код, я не знаю, как его изменить)
С другой стороны вы можете попробовать делать это в вашем view:
from rest_framework.exceptions import ValidationError
def create(self, request, *args, **kwargs):
_ = get_object_or_404(Blog, user=request.user.id, id=request.data.get("blog", False))
data = {}
if request.user.is_authenticated and request.user.is_published_post:
_data = request.data.copy()
print(_data)
_data["language"] = request.user.language
draft = DraftSurvey.objects.filter(
user=request.user.id, blog=_data["blog"]
)
if not _data.get("preview", False):
if draft and draft[0].preview:
_data["preview"] = draft[0].preview
# Пытаемся преобразовать из строки в list.
try:
_data["answers_set"] = json.loads(_data["answers_set"])
except json.JSONDecodeError:
raise ValidationError([
ValidationError("answers_set", code="Invalid JSON format.")
]) # django 3.0+
serializer = SurveySerializer(data=_data, user=request.user)
... # Остальной код
С другой стороны проблема может заключаться в том, что вы указываете как источник поле answers
, а передаете answers_set
:
class SurveySerializer(serializers.ModelSerializer):
tags = serializers.CharField(required=False, write_only=True)
answers_set = AnswerSerializer(source="answers", many=True) # Вот здесь.