Сериализация объектов внешнего ключа с помощью Django-HVAD TranslatedFields
Я вижу, что на SO есть несколько вопросов о сериализации на Django, но у меня возникли дополнительные сложности, потому что мои поля переведены (используя django-hvad
).
То, что у меня есть, работает, но я думаю, что это ужасно неэффективно, и, поскольку я новичок в Django, мне интересно, есть ли лучший способ.
Сейчас я собираю каждую из трех нужных мне моделей (Survey, SurveyQuestion, SurveyAnswer), сериализую каждую из них по отдельности, а затем соединяю их вместе перед преобразованием в JSON.
Эффект этого работает, как видно из оболочки django:
>>> qs = models.SurveyQuestion.objects.language('en').all().filter(survey=1)
>>> for q in qs:
... res.append({'question': q, 'answers' : models.SurveyAnswer.objects.language('en').all().filter(question=q.pk)})
...
>>> res = []
>>> res
[{'question': <SurveyQuestion: Who is the best Beatle?>, 'answers': [<SurveyAnswer: Paul McCartney>, <SurveyAnswer: George Harrison>, <SurveyAnswer: Ringo Starr>]}, {'question': <SurveyQuestion: Which album from The Beatles was the best?>, 'answers': [<SurveyAnswer: Yellow Submarine>, <SurveyAnswer: Revolver>, <SurveyAnswer: The White Album>]}]
Вот соответствующий код. Дайте мне знать, если вам нужно увидеть больше:
views.py
class SurveyDetail(APIView):
"""
Retrieve, update or delete a survey instance.
"""
def get_object(self, pk):
try:
user_language = self.request.GET.get('language')
return models.Survey.objects.language(user_language).get(pk=pk)
except models.Survey.DoesNotExist:
return HttpResponse(status=status.HTTP_404_NOT_FOUND)
def get_related_questions(self, pk):
try:
user_language = self.request.GET.get('language')
return models.SurveyQuestion.objects.language(user_language).all().filter(survey=pk)
except models.SurveyAnswer.DoesNotExist:
return HttpResponse(status=status.HTTP_404_NOT_FOUND)
def get_related_answers(self, pk):
try:
user_language = self.request.GET.get('language')
return models.SurveyAnswer.objects.language(user_language).all().filter(question=pk)
except models.SurveyAnswer.DoesNotExist:
return HttpResponse(status=status.HTTP_404_NOT_FOUND)
def get(self, request, pk, format=None):
survey = self.get_object(pk)
questions = self.get_related_questions(pk)
res = []
for q in questions:
res.append({
'question': SurveyQuestionSerializer(q).data,
'answers' : SurveyAnswerSerializer(self.get_related_answers(q.pk), many=True).data
})
resp_obj = {
'survey' : SurveySerializer(survey).data,
'data' : res
}
return JSONResponse(resp_obj)
def put(self, request, pk, format=None):
survey = self.get_object(pk)
serializer = SurveySerializer(survey, data=data)
if serializer.is_valid():
serializer.save()
return JSONResponse(serializer.data)
return JSONResponse(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
def delete(self, request, pk, format=None):
survey = self.get_object(pk)
survey.delete()
return HttpResponse(status=status.HTTP_204_NO_CONTENT)
serializers.py
class SurveySerializer(TranslatableModelSerializer):
class Meta:
model = models.Survey
fields = ['pk', 'title', 'description', 'slug']
class SurveyQuestionSerializer(TranslatableModelSerializer):
# survey = SurveySerializer(required=False)
class Meta:
model = models.SurveyQuestion
fields = ['pk', 'title', 'content', 'slug', 'survey', 'is_multi_select', 'has_other_field', 'required']
class SurveyAnswerSerializer(TranslatableModelSerializer):
# question = SurveyQuestionSerializer(required=False)
class Meta:
model = models.SurveyAnswer
fields = ['pk', 'title', 'slug', 'question']
1 ответ
Я понял это сам. Судя по всему, он ничем не отличается от непереведенных моделей, просто раньше у меня не было.
Ниже приведен исправленный код, который работает правильно. Обратите внимание на порядок каждого из сериализаторов, а также включение полей обратного внешнего ключа в качестве сериализаторов.
serializers.py
class SurveyAnswerSerializer(TranslatableModelSerializer):
class Meta:
model = models.SurveyAnswer
fields = ['pk', 'title', 'slug', 'question']
class SurveyQuestionSerializer(TranslatableModelSerializer):
answers = SurveyAnswerSerializer(many=True)
class Meta:
model = models.SurveyQuestion
fields = ['pk', 'title', 'content', 'slug', 'survey', 'is_multi_select', 'type', 'scale_min','scale_max', 'has_other_field', 'required', 'answers']
class SurveySerializer(TranslatableModelSerializer):
questions = SurveyQuestionSerializer(many=True)
class Meta:
model = models.Survey
fields = ['pk', 'title', 'description', 'slug', 'questions']
views.py
class SurveyDetail(APIView):
...
def get(self, request, pk, format=None):
survey = self.get_object(pk)
serializer = SurveySerializer(survey)
return JSONResponse(serializer.data)
Редактировать:
Оказывается, это не совсем работает. В этом сценарии Survey
объекты правильно переведены, но объекты, на которые ссылаются внешние ключи, например SurveyQuestion
а также SurveyAnswer
, не переводятся. Это означает, что вы получите смесь переведенных и непереведенных результатов.