Search code examples
djangodjango-modelsdjango-rest-frameworkdjango-views

objects in object Django API


Why when I get all products in included_lessons instead of objects I receive only their ID, when I want to receive full object: id, name and so on.

What I receive:

[
    {
        "id": 5,
        "author": "author",
        "name": "math product",
        "start_time": "2024-03-01T08:25:17Z",
        "min_users_in_group": 5,
        "max_users_in_group": 1,
        "included_lessons": [
            7,
            8,
            9
        ]
    }
]

What I want to receive:

[
    {
        "id": 5,
        "author": "author",
        "name": "math product",
        "start_time": "2024-03-01T08:25:17Z",
        "min_users_in_group": 5,
        "max_users_in_group": 1,
        "included_lessons": [
            {
                "id": 1,
                "name": "some name",
                "something else": "something else"
            },
            {
                "id": 2,
                "name": "some name 2",
                "something else": "something else 2"
            }
        ]
    }
]

Model:

class Product(models.Model):
    author = models.CharField(max_length=64)
    name = models.CharField(max_length=64)
    start_time = models.DateTimeField()
    min_users_in_group = models.IntegerField()
    max_users_in_group = models.IntegerField()
    included_lessons = models.ManyToManyField(Lesson, related_name='lessons')

    class Meta:
        db_table = 'product'

    def __str__(self):
        return self.name

Serializer:

class ProductSerializer(serializers.ModelSerializer):
    class Meta:
        model = Product
        fields = '__all__'

View model:

class ProductApiView(viewsets.ReadOnlyModelViewSet):
    queryset = Product.objects.all()
    serializer_class = ProductSerializer

I tried to change queryset in API View model, but it is useless


Solution

  • Specify a subserializer:

    class LessonSerializer(serializers.ModelSerializer):
        class Meta:
            model = Lesson
            fields = '__all__'
    
    
    class ProductSerializer(serializers.ModelSerializer):
        lessons = LessonSerializer(many=True)
    
        class Meta:
            model = Product
            fields = '__all__'

    You can further boost performance by fetching all related Lessons in one query:

    class ProductApiView(viewsets.ReadOnlyModelViewSet):
        queryset = Product.objects.prefetch_related('lessons')
        serializer_class = ProductSerializer