django TypeError:LinkPreview类型的对象不是JSON可序列化的

ccgok5k5  于 2023-08-08  发布在  Go
关注(0)|答案(1)|浏览(126)

我在我的django 3.2 API中使用了以下链接预览python包。https://github.com/meyt/linkpreview
当我从我的前端flutter应用程序发布一个链接并试图预览它时,我得到了所述的错误。
TypeError:LinkPreview类型的对象不是JSON可序列化的
以下是views.py我的flutter应用程序的点击率:

class PreviewLink(APIView):
    permission_classes = (IsAuthenticated, IsNotSuspended)
    throttle_scope = 'link_preview'

    def post(self, request):
        serializer = PreviewLinkSerializer(data=request.data, context={"request": request})
        serializer.is_valid(raise_exception=True)
        data = serializer.validated_data

        link = data.get('link')
        user = request.user

        link_preview = user.preview_link(link)

        return Response(link_preview, status=status.HTTP_200_OK)

class LinkIsPreviewable(APIView):
    permission_classes = (IsAuthenticated, IsNotSuspended)
    throttle_scope = 'link_preview'

    def post(self, request):
        serializer = PreviewLinkSerializer(data=request.data, context={"request": request})
        serializer.is_valid(raise_exception=True)
        data = serializer.validated_data

        link = data.get('link')

        try:
            is_previewable = link_preview(url=link)
        except Exception as e:
            is_previewable = False

        return Response({
            'is_previewable': is_previewable
        }, status=status.HTTP_200_OK)

字符串
PreviewLinkSerializer类

class PreviewLinkSerializer(serializers.Serializer):
    link = serializers.CharField(max_length=255, required=True, allow_blank=False)


link_preview函数:

def link_preview(url: str = None,content: str = None,parser: str = "html.parser"):
        
        """
        Get link preview
        """
        if content is None:
            try:
                grabber = LinkGrabber()
                content, url = grabber.get_content(url)
            except InvalidMimeTypeError:
                content = ""
    
        link = Link(url, content)
        return LinkPreview(link, parser=parser)


下面是包含preview_link()的User类:

def preview_link(self, link):
         return link_preview(url=link)


我只粘贴了上面的相关代码。完整的代码可以在我分享的链接中找到。

vc9ivgsu

vc9ivgsu1#

问题是

如果我们查看错误消息,可能会得到一些有用的信息:

TypeError: Object of type LinkPreview is not JSON serializable

字符串
在这里我们可以看出:
1.存在一个LinkPreview类型的对象
1.看起来我们在试图用JSON序列化它
查看您的代码,我可以看到link_preview正在返回一个LinkPreview对象。
然后我们在LinkIsPreviewable#post()方法中有如下内容:

is_previewable = link_preview(url=link)
return Response({
    'is_previewable': is_previewable
}, status=status.HTTP_200_OK)


这意味着我们要告诉Django序列化一个从strLinkPreview的Map,但Django不知道该怎么做。

解决方案

那我们该怎么解决呢?
我们必须首先序列化is_previewable,然后将其存储在dict中。
我无法在您提供的GitHub repository中找到LinkPreview类的序列化程序,因此您必须自己编写。
这样的东西会做:

class LinkSerializer(serializers.Serializer):
    url = serializers.CharField()
    content = serializers.CharField()

class GenericSerializer(serializers.Serializer):
    title = serializers.CharField()
    description = serializers.CharField()
    image = serializers.CharField()

class LinkPreviewSerializer(serializers.Serializer):
    link = LinkSerializer()
    generic = GenericSerializer(allow_null=True)


请注意,我只为Generic类型实现了它,您也可以为其余的源类型执行相同的操作。
然后可以使用它序列化LinkPreview对象,如下所示:

serialized_preview = LinkPreviewSerializer(instance=is_previewable).data


现在,可以将serialized_preview存储在dict中,并将其传递给Response构造函数。
注意:您没有发布User#preview_link()方法的内容,但是如果它也返回LinkPreview对象,则在将该对象传递给Response构造函数之前,您可能还需要序列化该对象。

相关问题