Search code examples
pythondjangodjango-rest-frameworkdjango-serializerpython-class

calling a class below of another class


I'm working on a django project with rest_framework and I have a problem with serializers. Here is my code:

class CategorySerializer(serializers.ModelSerializer):
    featured_product = ProductSerializer(read_only=True)
    class Meta:
        model = Category
        fields = [
            'title',
            'featured_product',
        ]

class ProductSerializer(serializers.ModelSerializer):
    category = CategorySerializer(read_only=True)
    class Meta:
        model = Product
        fields = [
            'title',
            'price',
            'category',
        ]

as you see, at ProductSerializer Im using CategorySerializer, and also at CategorySerializer I need to use ProductSerializer. if I run the code I get NameError: name 'ProductSerializer' is not defined.

First try:
I tried to write them in two different files and import them at top of both files but I got Circular Import error
Second try:
I defined an empty class with name of ProductSerializer class at the top of my code but it didn't worked.


Solution

  • If you accomplish what you are looking for, it will end in an infinite serializer process: CategorySerializer -> .featured_product -> ProductSerializer -> .category -> CategorySerializer -> .featured_product -> ProductSerializer -> ...

    To avoid that is better to create additional serializers, for example:

    class ProductListSerializer(serializers.ModelSerializer):
        class Meta:
            model = Product
            fields = [
                'title',
                'price',
            ]
    
    
    class CategoryListSerializer(serializers.ModelSerializer):
        class Meta:
            model = Category
            fields = [
                'title',
            ]
    
    
    class CategorySerializer(serializers.ModelSerializer):
        featured_product = ProductListSerializer(read_only=True)
    
        class Meta:
            model = Category
            fields = [
                'title',
                'featured_product',
            ]
    
    
    class ProductSerializer(serializers.ModelSerializer):
        category = CategoryListSerializer(read_only=True)
    
        class Meta:
            model = Product
            fields = [
                'title',
                'price',
                'category',
            ]
    

    But if you really want to have that circular relationship, you can do it using SerializerMethodField, for example:

    class CategorySerializer(serializers.ModelSerializer):
        featured_product = serializers.SerializerMethodField()
    
        class Meta:
            model = Category
            fields = [
                'title',
                'featured_product',
            ]
    
        def get_featured_product(self, obj):
            return ProductSerializer(obj.featured_product).data
    
    
    class ProductSerializer(serializers.ModelSerializer):
        category = CategorySerializer(read_only=True)
    
        class Meta:
            model = Product
            fields = [
                'title',
                'price',
                'category',
            ]