Django Rest Framework — M2M сквозной

#json #django #django-rest-framework #relationship #m2m

#json #django #django-rest-framework #взаимосвязь #m2m

Вопрос:

У меня возникли проблемы с извлечением всех полей, которые мне нужны, из сериализатора. Сценарий:

У меня есть 2 таблицы: Товар и склад. Эти таблицы связаны через связь M2M через сквозную таблицу, называемую InventoryStatus. Что мне нужно, так это получить информацию о товаре с вложенной информацией о складе поле состояния из таблицы InventoryStatus. Проблема в том, что я не могу получить поле «статус» ….

Модель:

 class InventoryItem(models.Model):
    id  = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    code = models.CharField(max_length=25, null=False, blank=True)
    orgid = models.ForeignKey('glonass.Company', null=True, related_name='inventory_items_company')
    title = models.CharField(max_length=150, null=False, blank=True)
    inventory = models.ManyToManyField('CompanyBranch', through='InventoryStatus', related_name='branch_iventoryStatus')

class CompanyBranch(BaseDataDescTime, LocationInfo, PostInfo, PoboxInfo, ContactInfo):
    id  = models.UUIDField(primary_key=True, default=uuid.uuid4,
    orgid = models.ForeignKey('glonass.Company', null=True, related_name='branches')
    slug = models.SlugField(max_length=150, blank=True, null=False)

class InventoryStatus(models.Model):
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
    inventoryitem = models.ForeignKey('InventoryItem', related_name='inventory_status_items', null=True)
    orgid = models.ForeignKey('Company', null=True, related_name='inventory_status_company')
    companybranch = models.ForeignKey('CompanyBranch', related_name='inventory_status_warehouses', null=True)
    status = models.DecimalField(max_digits=9, decimal_places=2, null=True, blank=True, default=0)
  

Сериализатор:

 class InventoryStatusSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = InventoryStatus

class CompanyBranchSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = CompanyBranch

class InventoryItemSerializer(serializers.HyperlinkedModelSerializer):
    inventory = CompanyBranchSerializer(many=True)

    class Meta:
        model = InventoryItem
  

Требуется вывод:

 [
    {
        'id': 'xxxxxxxxxxxxx',
        'title': 'Car',
        'inventory': [
            {
                'id': 'yyyyyyyyyyy',
                'title': 'warehouse 1',
                'status': 50
            },
            {
                'id': 'zzzzzzzzzzzz',
                'title': 'warehouse 2',
                'status': 10
            }
        ]
    }
]
  

Комментарии:

1. И что вы получаете со своими сериализаторами? Все без 'status' поля?

2. ДА… и когда я использую inventory = InventoryStatusSerializer(many = True), я получаю идентификатор подразделения компании вместо идентификатора из таблицы InventoryStatus … хотя, когда у меня есть представление InventoryStatus … в представлении InventoryStatus я могу получить поля, как из любой другой таблицы… но я не могу вложить этот результат в результат элементов

Ответ №1:

Проблема в том, что отношения M2M предоставляют непосредственно связанный объект без какой-либо информации в таблице «через», что затрудняет сериализацию и получение некоторой информации в таблице «через». Чтобы решить эту проблему, я обычно использую отношение «through» для получения информации из таблицы «through» и связанных элементов.

В вашем случае это может выглядеть примерно так:

 class InventoryStatusSerializer(serializers.ModelSerializer):
    companybranch = CompanyBranchSerializer(many=True, read_only=True)
    class Meta:
        model = InventoryStatus
        fields = ('status', 'companybranch')

class InventoryItemSerializer(serializers.ModelSerializer):
    inventory = InventoryStatusSerializer(source='inventory_status_items', many=True, read_only=True)

    class Meta:
        model = InventoryItem
  

Это дало бы результат, подобный (Примечание: я думаю, вы имели в виду «slug», а не «title» в элементах инвентаря вашего примера):

 [
  {
    'id': 'xxxxxxxxxxxxx',
    'title': 'Car',
    'inventory': [
        {
            'status': 50
            'companybranch': {
                'slug': 'warehouse 1',
                'id': 'yyyyyyyyyyy',                }
        },
        {
            'status': 10
            'companybranch':  {
                'slug': 'warehouse 2',
                'id': 'zzzzzzzzzzzz',
            }
        }
    ]
  }
]
  

Теперь, если вы хотите сгладить вывод, просто измените InventoryStatusSerializer :

 class InventoryStatusSerializer(serializers.ModelSerializer):
    id = serializers.ReadOnlyField(source='companybranch.id')
    slug = serializers.ReadOnlyField(source='companybranch.slug')
    class Meta:
        model = InventoryStatus
        fields = ('status', 'id', 'slug')
  

Ответ №2:

Вам необходимо добавить раздел полей в классы сериализаторов следующим образом:

    class CompanyBranchSerializer(serializers.HyperlinkedModelSerializer):
      class Meta:
         model = CompanyBranch
         fields = = ('id', 'orgid', 'slug')
  

вам также нужно сделать то же самое для других.