Я пытаюсь изменить вывод сериализатора Django.
Представление на основе классов имеет функцию get_projects, которая возвращает набор запросов экземпляров контракта.
projects = Project.objects.all()
contracts = Contract.objects.filter(project__in=projects)
Отношения контракта и проекта — один ко многим:
class Contract(models.Model):
project = models.ForeignKey(Project)
Теперь у меня есть такой 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:
[
{
"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"
},
]
Я хотел бы изменить вывод сериализатора - сгруппировать контракты для конкретных проектов, например:
[
{
"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",
},
....
]
},
]
Как я могу это сделать?
Отвечает ли это на ваш вопрос? Вложенная модель Django или сериализаторы






Для этого вы можете попробовать это
class ContactSerializer(serializers.ModelSerializer):
class Meta:
model = Contract
fields = ["contract_guid", "contract_number"]
class ProjectSerializer(serializers.ModelSerializer):
contracts = ContactSerializer(many=True)
class Meta:
model = Project
fields = ["project_guid", "project_name", "contracts"]
И не забывайте использовать предварительную выборку для оптимизации вашего запроса.
Проблема была в наборе запросов. Я провел рефакторинг qs в get_projects:
projects = Project.objects.filter(active=True).prefetch_related(
Prefetch('contract_set', queryset=Contract.objects.filter(**filters), to_attr='contracts')
)
И реорганизовал MySerializer следующим образом:
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)
Спасибо SerhiiL за подсказку с prefetch_related.
Сначала вам следует создать
ContractSerializerи использовать его сериализатор внутриProjectSerializerполя контрактаcontracts = ContractSerializer(blabla....