I try to change output of Django serializer.
Class-based view has function get_projects that returns queryset of Contract instances.
projects = Project.objects.all()
contracts = Contract.objects.filter(project__in=projects)
Relationship of Contract and Project is one-to-many:
class Contract(models.Model):
project = models.ForeignKey(Project)
Now I have such MySerializer:
class MySerializer(serializers.Serializer):
project_guid = serializers.UUIDField(source='guid')
project_name = serializers.CharField(source='name')
contract_guid = serializers.UUIDField(source='guid')
contract_number = serializers.CharField(source='number')
MySerializer's response is:
[
{
"projectGuid": "project_guid_1",
"projectName": "project_name_1",
"contractGuid": "contract_guid_1",
"contractNumber": "contract_number_1"
},
{
"projectGuid": "project_guid_1",
"projectName": "project_name_1",
"contractGuid": "contract_guid_2",
"contractNumber": "contract_number_2"
},
{
"projectGuid": "project_guid_2",
"projectName": "project_name_2",
"contractGuid": "contract_guid_4",
"contractNumber": "contract_number_4"
},
{
"projectGuid": "project_guid_2",
"projectName": "project_name_2",
"contractGuid": "contract_guid_5",
"contractNumber": "contract_number_5"
},
]
I would like to change serializer output - to group contracts for exact projects like this:
[
{
"project_guid": "project_guid_1",
"project_name": "project_name_1",
"contracts": [
{
"contract_guid": "contract_guid_1",
"contract_number": "contract_number_1",
},
{
"contract_guid": "contract_guid_2",
"contract_number": "contract_number_2",
},
....
]
},
{
"project_guid": "project_guid_2",
"project_name": "project_name_2",
"contracts": [
{
"contract_guid": "contract_guid_4",
"contract_number": "contract_number_4",
},
{
"contract_guid": "contract_guid_5",
"contract_number": "contract_number_5",
},
....
]
},
]
How can I do this?
The problem was with the queryset. I refactored qs in get_projects:
projects = Project.objects.filter(active=True).prefetch_related(
Prefetch('contract_set', queryset=Contract.objects.filter(**filters), to_attr='contracts')
)
And refactored MySerializer like this:
class ContractSerializer(serializers.Serializer):
contract_guid = serializers.UUIDField(source='guid')
contract_number = serializers.CharField(source='number')
class MySerializer(serializers.Serializer):
project_guid = serializers.UUIDField(source='guid')
project_name = serializers.CharField(source='name')
contracts = ContractSerializer(many=True)
Thanks to SerhiiL
for hint with prefetch_related.