【问题标题】:DRF how can I return only the first serialized object to the view?DRF 如何仅将第一个序列化对象返回到视图?
【发布时间】:2020-06-17 03:24:57
【问题描述】:

在 DRF 中,有没有办法让单个嵌套图像显示在视图中。在我的示例中,您可以看到列出了 2 张照片。检索和显示第一张照片的最佳解决方案是什么?此视图将显示房屋列表,我不希望显示每张照片,因为可能有一些用户上传了 30 多张照片。

            "url": "http://127.0.0.1:8000/api/v1/listings/1/",
            "address": "8753 sherwood dr apt 111",
            "image_set": [
                {
                    "photo": "http://127.0.0.1:8000/media/listing_images/front-view.png"
                },
                {
                    "photo": "http://127.0.0.1:8000/media/listing_images/image34453.png
                }
            ]
        },


class ImageSerializerForListingDetail(serializers.ModelSerializer):
    photo = serializers.ImageField(use_url=True, allow_empty_file=True)
    class Meta:
        model = Image
        fields = ('photo', )
    def get_image_url(self, listing):
        return listing.photo.url


class ListingListSerializer(serializers.HyperlinkedModelSerializer):
    photo = ImageSerializerForListingDetail(many=True, required=False)
    class Meta:
        model = Listing
        fields = ('url', 'address', 'photo', )


class ListingViewSet(viewsets.ModelViewSet):
    queryset = Listing.objects.all().order_by('id')
    permission_classes = [IsOwnerOrReadOnly, ]
    serializer_classes = {
        'list': ListingListSerializer,
        'retrieve': ListingSerializer
    }
    default_serializer_class = ListingSerializer

    def get_serializer_class(self):
        return self.serializer_classes.get(self.action, self.default_serializer_class)

    def create(self, request, *args, **kwargs):
        serializer = ListingSerializer(data=request.data, files=request.FILES)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

我刚刚尝试的当前代码,返回一个空的照片列表.... #

class ImageSerializerForListingDetail(serializers.ModelSerializer):
    photo = serializers.ImageField(allow_empty_file=True)

    class Meta:
        model = Image
        fields = ('photo', )

    def get_image_url(self, listing):
        return listing.photo.url



class ListingListSerializer(serializers.HyperlinkedModelSerializer):
    first_image = ImageSerializerForListingDetail(many=True, required=False)

    class Meta:
        model = Listing
        fields = ('url', 'address', 'first_image', )

    def get_first_image(self, obj):
        first_image = Image.objects.filter(listing=obj).first()
        first_image_serializer = ImageSerializerForListingDetail(first_image)
        return first_image_serializer.data

【问题讨论】:

    标签: django django-rest-framework django-rest-viewsets


    【解决方案1】:

    您只能将第一项传递给您的序列化程序:

    def get_queryset(self):
        return  Listing.objects.all().order_by('id').first() if self.action == 'retrieve' else Listing.objects.all().order_by('id')
    

    【讨论】:

    • 如何将图像添加到该列表中?我正在尝试某种额外的过滤?由于图像具有列表的外键。
    • 这是我的图片模型class Image(models.Model): photo = models.ImageField(blank=True, upload_to=get_image_filename) listing = models.ForeignKey(Listing, on_delete=models.CASCADE)
    • 我不明白你想要什么。你能详细解释一下吗?
    • 我的目标是上传第一张图片。我只处理两个模型。一个列表模型和一个图像模型。图像模型有两个字段,照片和列表。其中列表是列表模型的外键。我已经用我尝试的最新代码更新了帖子。它现在返回一个空查询。
    【解决方案2】:

    由于我不太确定您的模型如何以及您想展示的第一张照片(例如最新上传的、首次上传的、最新的 id)。我将使用一个通用示例来解释解决方案。

    尝试serializers.SerializerMethodField() 自定义您要呈现最新字段的字段。

    假设用户模型中有一个组列表,并且您希望在用户的详细信息中显示最新的组 ID。

    这是一个例子:

    class UserSerializer(serializers.ModelSerializer):
        latest_group_id = serializers.SerializerMethodField()
    
        def get_latest_group_id(self, obj):
            return Group.objects.filter(user=obj).latest('id').id
    

    由于您想显示照片 url 而不是 id,所以这里是伪代码。

    class UserProfileSerializer(serializers.ModelSerializer):
        latest_image = serializers.SerializerMethodField()
    
        def get_latest_image(self, obj):
            latest_image = Image.objects.filter(user=obj).latest('id')
            latest_image_serializer = ImageSerializerForListingDetail(latest_image)
            # Deal with edge cases, e.g. latest_image_serializer is not valid
            return latest_image_serializer.data
    

    【讨论】:

    • 我的目标是上传第一张图片。我只处理两个模型。 Listing 模型和 Image 模型。图像模型有两个字段,照片和列表。其中列表是列表模型的外键。我正在玩弄你的代码,现在试图找到正确的解决方案。
    • 从您在问题中发布的最新代码来看,ListingListSerializer 中的 first_image 字段应为 first_image = serializers.SerializerMethodField()
    • 刚刚解决了这个问题。仍然得到一个空查询集,我的 first_image 字段将是.. { "url": "http://127.0.0.1:8000/api/v1/listings/2/", "address": "4848 north florida dr" }
    • 是否有与您的列表相关的图片(id=2)?
    • 是的,当我实际点击该网址并进入详细视图时,有两张与该列表相关联的照片。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-05
    • 1970-01-01
    • 1970-01-01
    • 2015-11-11
    • 1970-01-01
    • 2011-09-27
    相关资源
    最近更新 更多