Search code examples
pythondjangodjango-modelsdjango-rest-frameworkdjango-serializer

ManyToManyField value in Django REST Framework


So when I am routing to api/ to view my models I am not seeing what I expected to see. I wanted to see the names of the strats that I grouped in Strat_Basket model in the variable basket but instead I see their ids which is generated by DJANGO automatically. I want to see the names rather than numbers in the strat_basket view. It is more informative that's why.

models.py

class Strats(models.Model):
    name = models.CharField(max_length=64)
class Strats_Basket(models.Model):
    name = models.CharField(max_length=64)
    basket = models.ManyToManyField(Strats, blank=True, related_name='list')

serializers.py:

class StratsSerializer(serializers.ModelSerializer):
    class Meta:
        model = Strats
        fields = ('id', 'name')
class Strats_BasketSerializer(serializers.ModelSerializer):
    class Meta:
        model = Strats_Basket
        fields = ('id', 'name', 'basket')

views.py:

class StratsView(viewsets.ModelViewSet):
    serializer_class = StratsSerializer
    queryset = Strats.objects.all()
class Strats_BasketView(viewsets.ModelViewSet):
    serializer_class = Strats_BasketSerializer
    queryset = Strats_Basket.objects.all()

urls.py:

router = routers.DefaultRouter()
router.register(r'strats', views.StratsView, 'strats')
router.register(r'strats_basket', views.Strats_BasketView, 'strats_basket')

API OUTPUT:

strats:

[
    {
        "id": 1,
        "name": "strat1"
    },
    {
        "id": 2,
        "name": "strat2"
    },
    {
        "id": 3,
        "name": "strat3"
    },
    {
        "id": 4,
        "name": "strat4"
    },
    {
        "id": 5,
        "name": "strat5"
    },
    {
        "id": 6,
        "name": "strat6"
    }
]

strats_basket: Instead of 1,2,4 I want to see strat1, strat2, strat4.

[
    {
        "id": 1,
        "name": "Basket 1",
        "basket": [
            1,
            2,
            4
        ]
    },
    {
        "id": 2,
        "name": "Basket 2",
        "basket": [
            3,
            5,
            6
        ]
    }
]

Solution

  • You can use SerializerMethodField and inside the method return names list using values_list with flat=True

    class Strats_BasketSerializer(serializers.ModelSerializer):
         
        basket = serializers.SerializerMethodField()
         
        def get_basket(self, obj):
            return obj.basket.all().values_list('name', flat=True)
    
        class Meta:
            model = Strats_Basket
            fields = ('id', 'name', 'basket')