Как изменить кверисет в Django?

Я пытаюсь изменить вывод сериализатора Django.

В представлении на основе классов есть функция get_projects, которая возвращает набор экземпляров Contract.

Отношения между Contract и Project - один-ко-многим:

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",
    },
    ....
  ]
 },
]

Как я могу это сделать?

Для этого вы можете попробовать следующее

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"]

И не забывайте использовать prefetch relatedдля оптимизации запроса.

Проблема была связана с набором запросов. Я отрефакторил 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.

Вернуться на верх