Добавление поля url, связывающего с действием в сериализаторе в DRF

Я использую django rest framework. Я хочу включить url действия, определенного в представлении, в его сериализатор.

Мой serializers.py:


    from rest_framework import serializers
    
    
    class CommentSerializer(serializers.ModelSerializer):
        """Serializer for comments."""
    
        class Meta:
            model = Comment
            fields = ["id", "item", "author", "content", "date_commented", "parent"]
    
    
    class ItemDetailSerializer(serializers.ModelSerializer):
        """Serializer for items (for retrieving/detail purpose)."""
    
        category = CategorySerializer(many=True, read_only=True)
        media = MediaSerializer(many=True, read_only=True)
        brand = BrandSerializer(many=False, read_only=True)
        specifications = serializers.SerializerMethodField(source="get_specifications")
        comments = ??????????????????????????????????????????????????
    
        class Meta:
            model = Item
            fields = [
                "id",
                "slug",
                "name",
                "description",
                "brand",
                "show_price",
                "location",
                "specifications",
                "is_visible",
                "is_blocked",
                "created_at",
                "updated_at",
                "seller",
                "category",
                "media",
                "comments",
                "users_wishlist",
                "reported_by",
            ]
            read_only = True
            editable = False
            lookup_field = "slug"
    
        def get_specifications(self, obj):
            return ItemSpecificationSerializer(obj.item_specification.all(), many=True).data

Мой views.py:


    from rest_framework import viewsets, mixins, status
    from ramrobazar.inventory.models import Item, Comment
    from ramrobazar.drf.serializers ItemSerializer, ItemDetailSerializer, CommentSerializer
    from rest_framework.permissions import IsAuthenticatedOrReadOnly
    from rest_framework.filters import SearchFilter
    from django_filters.rest_framework import DjangoFilterBackend
    
    class ItemList(viewsets.GenericViewSet, mixins.ListModelMixin):
        """View for listing and retrieving all items for sale."""
    
        queryset = Item.objects.all()
        serializer_class = ItemSerializer
        serializer_action_classes = {
            "retrieve": ItemDetailSerializer,
        }
        permission_classes = [IsAuthenticatedOrReadOnly]
        lookup_field = "slug"
        filter_backends = [DjangoFilterBackend, SearchFilter]
        filterset_fields = [
            "category__slug",
            "brand__name",
        ]
        search_fields = ["name", "description", "category__name", "brand__name", "location"]
    
        def get_serializer_class(self):
            try:
                return self.serializer_action_classes[self.action]
            except:
                return self.serializer_class
    
        def retrieve(self, request, slug=None):
            item = self.get_object()
            serializer = self.get_serializer(item)
            return Response(serializer.data)
        
        @action(detail=True, methods=['GET'])
        def comments(self, request, slug=None):
            item = Item.objects.get(slug=slug)
            queryset = Comment.objects.filter(item=item)
            serializer = CommentSerializer(queryset, many=True)
            return Response(serializer.data, status=status.HTTP_200_OK)

У меня есть действие с именем comments в представлении ItemList, которое дает все комментарии определенного элемента. Я могу получить подробную информацию об элементе из url /api/items/<slug>. Я могу получить все комментарии элемента из url api/items/<slug>/comments. Я хочу включить поле comments в сериализатор ItemDetailSerializer, которое является ссылкой на api/items/<slug>/commments. Как я могу этого добиться?

Вы можете сделать это через SerializerMethodField и reverse:

class ItemDetailSerializer(serializers.ModelSerializer):
    ...
    comments = serializers.SerializerMethodField(source="get_comments")

    ...

    def get_comments(self, obj):
        return reverse(YOUR_URL_NAME, kwargs={'slug': obj.slug})

попробуйте это:

class ItemDetailSerializer(serializers.ModelSerializer):
...

    comments = serializers.CharField(max_length=100, required=False)

    def create(self, validated_data):
        validated_data['comments'] = self.context['request'].build_absolute_uri() + 'comments'
        return super(ContentGalleryListSerializer, self).create(validated_data)
You can use the HyperlinkedIdentityField for this:
comments = serializers.HyperlinkedIdentityField(
    view_name='item-comments',
    lookup_field='slug'
)
This will then render a comments field that contains a URL to the item-comments view, with the slug as lookup parameter.
You will need to register the view with the name item-comments, for example with:
urlpatterns = [
    path('items/<slug>/comments/', ItemList.as_view({'get': 'comments'}), name='item-comments')
]
Note that normally nested routes are discouraged, and you'd put the comments in a separate view. But the above should work.
Вернуться на верх