Reputation: 8510
I see there are several questions on SO about serialization on Django already, but I'm having additional complexity because my fields are translated (using django-hvad
).
What I have kinda works but I imagine it's horribly inefficient, and since I'm new to Django, am wondering if there's a better way.
What I'm doing now is getting each one of the three models I need (Survey, SurveyQuestion, SurveyAnswer), serializing each individually, and then knitting them together before converting to JSON.
The effect of this is working, as seen in the django shell:
>>> 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>]}]
Here's the relevant code. Let me know if you need to see more:
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)
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']
Upvotes: 0
Views: 153
Reputation: 8510
I figured it out myself. Apparently, it's no different than on untranslated models, I just didn't have it right before.
Below is the corrected code which works properly. Note the order of each of the serializers and also the inclusion of the reverse foreign key fields as serializers.
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']
class SurveyDetail(APIView):
...
def get(self, request, pk, format=None):
survey = self.get_object(pk)
serializer = SurveySerializer(survey)
return JSONResponse(serializer.data)
turns out this doesn't completely work. In this scenario, the Survey
objects are correctly translated, but the objects referenced by the foreign keys, like SurveyQuestion
and SurveyAnswer
, are not translated. This means you get a mix of translated and untranslated results.
Upvotes: 0