Django Как аннотировать/группировать по и отображать в сериализаторе
У меня есть следующая модель
class ModelAnswer(BaseModel):
questions = models.ForeignKey(
to=Question,
on_delete=models.CASCADE
)
answer = models.TextField()
user = models.ForeignKey(User, on_delete=models.CASCADE)
В основном используется случай, когда ответ может быть добавлен несколько раз, т.е. сразу 3 ответа могут быть добавлены и все ответы должны быть добавлены для конкретного вопроса
Я просто сделал еще одну модель, чтобы отслеживать эти вещи в следующей модели для моего удобства.
class AnswerLog(BaseModel):
answer = models.ForeignKey(to=ModelAnswer, on_delete=models.CASCADE, null=True, blank=True)
user = models.ForeignKey(User, on_delete=models.CASCADE, null=True, blank=True)
order = models.PositiveIntegerField(null=True, blank=True)
Я получаю ответ в таком формате
[
{
"answer":{
"id":42,
"user":1,
"questions":"what did you do today",
"subcategory":"Circumstance",
"is_intentional":"False",
"answer":"I played well",
"created_at":"2022-09-05T21:00:57.604051"
},
"order":1,
"category":"sports"
},
{
"answer":{
"id":43,
"user":1,
"questions":"what was your achievment?",
"subcategory":"Result",
"is_intentional":"False",
"answer":"a broked my leg",
"created_at":"2022-09-05T21:00:57.626193"
},
"order":1,
"category":"sports"
}
]
Я просто хочу, чтобы мой вышеупомянутый ответ был немного проще в формате, таким образом, просто объедините по порядку и категории, потому что оба будут (категория может быть такой же для другого ответа, поэтому порядок будет отличаться только для следующего ответа, т.е. 2)
[{
"answer":[{
"id":42,
"user":1,
"questions":"what did you do today",
"subcategory":"Circumstance",
"is_intentional":"False",
"answer":"I played well",
"created_at":"2022-09-05T21:00:57.604051"
},{
"id":43,
"user":1,
"questions":"what was your achievment?",
"subcategory":"Result",
"is_intentional":"False",
"answer":"a broked my leg",
"created_at":"2022-09-05T21:00:57.626193"
}],
"order":1,
"category":"sports",
}
]
Мой сериализатор выглядит следующим образом
class AnswerLogSerializer(serializers.ModelSerializer):
answer = ListAnswerSerializer()
category = serializers.CharField(source='answer.questions.category.name')
class Meta:
model = AnswerLog
fields = ['answer','order', 'category']
Мое мнение таково
class ListAnswerLogView(generics.ListAPIView):
serializer_class = serializers.AnswerLogSerializer
def get_queryset(self):
return AnswerLog.objects.all()
View
from collections import defaultdict
class ListAnswerLogView(ListAPIView):
serializer_class = AnswerLogSerializer
def get_queryset(self):
grouped_answers = defaultdict(lambda: dict(answer=set()))
for answer_log in AnswerLog.objects.all():
grouped_by_key = (
answer_log.order,
answer_log.answer.questions.category
)
grouped_answers[grouped_by_key]['answer'].add(answer_log.answer)
for key in grouped_answers:
grouped_answers[key].update(dict(
order=key[0],
question_category=key[1]
))
return grouped_answers.values()
Serializer
class AnswerLogSerializer(serializers.ModelSerializer):
answer = ListAnswerSerializer(many=True)
category = serializers.CharField(source='question_category.name')
class Meta:
model = AnswerLog
fields = ['answer', 'order', 'category']
P.S. Я много раз пытался решить проблему просто используя возможности django queryset, но каждый из них приводит к проблеме. Поэтому я пошел этим путем, используя словарь для решения проблемы.