3

Im having trouble with retrieving all fields I need from serializer. Scenario:

I have 2 tables: Item & Warehouse. Those tables are connected via M2M relationship via through table called InventoryStatus. What I need is to get Item info with nested warehouse info + status field from InventoryStatus Table. The problem is, I cant get the "status" field....

Model:

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)

Serializer:

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

Output Needed:

[
    {
        'id': 'xxxxxxxxxxxxx',
        'title': 'Car',
        'inventory': [
            {
                'id': 'yyyyyyyyyyy',
                'title': 'warehouse 1',
                'status': 50
            },
            {
                'id': 'zzzzzzzzzzzz',
                'title': 'warehouse 2',
                'status': 10
            }
        ]
    }
]
Jakub Mana
  • 81
  • 1
  • 9
  • And what you get with your serializers? Everything without `'status'` field? – vishes_shell Oct 10 '16 at 18:57
  • yes... and when I use inventory = InventoryStatusSerializer(many=True) i got CompanyBranch ID instead of Id from InventoryStatus table... even though when I have InventoryStatus view ... in InventoryStatus view i can get the fields like from any other table... but i cant nest this result into the result of Items – Jakub Mana Oct 10 '16 at 19:18

2 Answers2

2

The problem is that M2M relations give directly the related object without any info on the "through" table, making it a pain when you want to serialize and grab some info in the "through" table. To solve this, I usually use the "through" relation to grab the information from the "through" table and the related items.

In your case it could look something like:

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

This would give output like (Note: I think you meant 'slug', not 'title' in the inventory items of your example):

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

Now if you want to flatten the output, just change the 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')
Michael Rigoni
  • 1,946
  • 12
  • 17
0

You need to add fields section to Serializers' Classes like following:

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

you also need to do the same for the others.