Search code examples
djangoimagedjango-rest-frameworkrequestdjango-serializer

How to pass request as an argument to serializer in serializer method field


I have a main serializer, and I also have a serializer for my BOOK model so I made a method to return a serialized queryset using my BOOK SERIALIZER

BUT the problem is ** I can't access my main serializer context through BookSerializer**

What can I do?

Views.py:

class BookMainPage(ListModelMixin, RetrieveModelMixin, GenericViewSet):
    queryset = Book.objects.select_related('owner').all()

    def get_serializer_context(self):
        return {'user': self.request.user, 'book_id': self.kwargs.get('pk'), 'request': self.request}

    def get_serializer_class(self):
        if self.kwargs.get('pk') is None:
            return MainPageSerializer
        return BookComplexSerializer

MainPageSerializer:

class MainPageSerializer(serializers.Serializer):
    @staticmethod
    def get_new_books(self):
        return BookSimpleSerializer(Book.objects.all().order_by('-created_at')[:10], many=True).data

    @staticmethod
    def get_popular_books(self):
        return BookSimpleSerializer(Book.objects.all().order_by('-bookRate')[:10], many=True).data

    @staticmethod
    def get_most_borrowed(self):
        return BookSimpleSerializer(Book.objects.all().order_by('-wanted_to_read')[:10], many=True).data

    new_books = serializers.SerializerMethodField(method_name='get_new_books')
    popular_books = serializers.SerializerMethodField(method_name='get_popular_books')
    most_borrowed_books = serializers.SerializerMethodField(method_name='get_most_borrowed')

BookSimpleSerializer:

class BookSimpleSerializer(serializers.ModelSerializer):
    class Meta:
        model = Book
        fields = ['id', 'picture']

    def get_picture(self, obj: Book):
        request = self.context['request']
        photo_url = obj.picture.url
        return request.build_absolute_uri(photo_url)

    picture = serializers.SerializerMethodField(method_name='get_picture')


class CategorySimpleSerializer(serializers.ModelSeria

Solution

  • You can intiialiaze your serializer passing a context with your request in the MethodField method:

    class MainPageSerializer(serializers.Serializer):
        def get_new_books(self):
            return BookSimpleSerializer(
                Book.objects.all().order_by('-created_at')[:10], 
                many=True, 
                context={"request": self.context["request"]}
            ).data
    
        def get_popular_books(self):
            return BookSimpleSerializer(
                Book.objects.all().order_by('-bookRate')[:10], 
                many=True, 
                context={"request": self.context["request"]}
            ).data
    
        def get_most_borrowed(self):
            return BookSimpleSerializer(
                Book.objects.all().order_by('-wanted_to_read')[:10], 
                many=True, 
                context={"request": self.context["request"]}
            ).data
    
        new_books = serializers.SerializerMethodField(method_name='get_new_books')
        popular_books = serializers.SerializerMethodField(method_name='get_popular_books')
        most_borrowed_books = serializers.SerializerMethodField(method_name='get_most_borrowed')
    
    

    And i remove the staticmethod decorator. Your method does not have to be static