【问题标题】:Object of type <> is not JSON serializable Django REST Framework<> 类型的对象不是 JSON 可序列化的 Django REST Framework
【发布时间】:2023-01-10 11:41:31
【问题描述】:

我正在尝试使用 Django Rest Framework 在基于类的视图中创建搜索功能,但它似乎不起作用。

当我尝试搜索一些客户时,它给了我一个错误:

raise TypeError(f'Object of type {o.class.name} '
TypeError: Object of type Customer is not JSON serializable

我知道外面有一些问题看起来像我的问题,但我认为他们中的任何一个都不能帮助我。我对 Django REST 框架有点陌生。

我的看法:

class staff_search_partial(generics.ListAPIView):
    renderer_classes = [JSONRenderer, TemplateHTMLRenderer]
    template_name = 'BankApp/staff_search_partial.html'
    serializer_class = CustomerSerializer
    permissions_classes = [permissions.IsAuthenticated, ]

    def post(self, request):
        assert request.user.is_staff, 'Customer user routing staff view.'

        search_term = request.POST['search_term']
        print(type(search_term))
        customers = Customer.objects.filter(
                Q(user__username__contains=search_term)   |
                Q(user__firstname__contains=search_term) |
                Q(user__lastname__contains=search_term)  |
                Q(user__email__contains=search_term)      |
                Q(personalid__contains=search_term)      |
                Q(phone_contains=search_term)
            )[:15]

        return Response({'customers': customers})

客户模型:

class Customer(models.Model):
    user        = models.OneToOneField(User, primary_key=True, on_delete=models.PROTECT)
    rank        = models.ForeignKey(Rank, default=2, on_delete=models.PROTECT)
    personal_id = models.IntegerField(db_index=True)
    phone       = models.CharField(max_length=35, db_index=True)

    @property
    def full_name(self) -> str:
        return f'{self.user.first_name} {self.user.last_name}'

    @property
    def accounts(self) -> QuerySet:
        return Account.objects.filter(user=self.user)

    @property
    def can_make_loan(self) -> bool:
        return self.rank.value >= settings.CUSTOMER_RANK_LOAN

    @property
    def default_account(self) -> Account:
        return Account.objects.filter(user=self.user).first()

    def make_loan(self, amount, name):
        assert self.can_make_loan, 'User rank does not allow for making loans.'
        assert amount >= 0, 'Negative amount not allowed for loan.'
        loan = Account.objects.create(user=self.user, name=f'Loan: {name}')
        Ledger.transfer(
            amount,
            loan,
            f'Loan paid out to account {self.default_account}',
            self.default_account,
            f'Credit from loan {loan.pk}: {loan.name}',
            is_loan=True
        )

客户序列化程序:

class CustomerSerializer (serializers.ModelSerializer):

    class Meta:
        fields = ('user', 'rank', 'personal_id', 'phone', 'full_name', 'accounts', 'can_make_loan', 'default_account')
        model = Customer

【问题讨论】:

  • 您在返回 Response({'customers': customers}) 时没有序列化客户,通过 CustomerSerializer 传递客户然后返回序列化数据

标签: django serialization django-rest-framework django-class-based-views


【解决方案1】:

正如我在您的问题下的评论中所写,您应该序列化查询集

class staff_search_partial(generics.ListAPIView):
    renderer_classes = [JSONRenderer, TemplateHTMLRenderer]
    template_name = 'BankApp/staff_search_partial.html'
    serializer_class = CustomerSerializer
    permissions_classes = [permissions.IsAuthenticated, ]

    def post(self, request):
        assert request.user.is_staff, 'Customer user routing staff view.'

        search_term = request.POST['search_term']
        print(type(search_term))
        customers = Customer.objects.filter(
            Q(user__username__contains=search_term)   |
            Q(user__firstname__contains=search_term) |
            Q(user__lastname__contains=search_term)  |
            Q(user__email__contains=search_term)      |
            Q(personalid__contains=search_term)      |
            Q(phone_contains=search_term)
        )[:15]
        customers_data = CustomerSerializer(customers, many=True).data
        return Response({'customers': customers_data})

【讨论】:

    【解决方案2】:

    您必须像这样编辑您的视图类

    class staff_search_partial(generics.ListAPIView):
        renderer_classes = [JSONRenderer, TemplateHTMLRenderer]
        template_name = 'BankApp/staff_search_partial.html'
        serializer_class = CustomerSerializer
        permissions_classes = [permissions.IsAuthenticated, ]
    
        def post(self, request):
            assert request.user.is_staff, 'Customer user routing staff view.'
    
            search_term = request.POST['search_term']
            print(type(search_term))
            customers = Customer.objects.filter(
                    Q(user__username__contains=search_term)   |
                    Q(user__firstname__contains=search_term) |
                    Q(user__lastname__contains=search_term)  |
                    Q(user__email__contains=search_term)      |
                    Q(personalid__contains=search_term)      |
                    Q(phone_contains=search_term)
                )[:15]
    
            return customers
    

    只是回头客不是字典

    【讨论】:

    • 现在它给了我一个:AssertionError: Expected a Response, HttpResponse or HttpStreamingResponse to be returned from the view, but received a <class 'django.db.models.query.QuerySet'>
    • 那是因为视图应该返回 Response、HttpResponse 或 HttpStreamingResponse,而不是 queryset
    【解决方案3】:

    @TrueGopnika 的回答是正确的,但我认为您不需要为搜索过滤器编写查询集。您可以使用 Django REST 框架搜索过滤器,这可以减少您的工作量。请仔细阅读此文档https://www.django-rest-framework.org/api-guide/filtering/#searchfilter

    【讨论】:

    • 我知道 DRF 过滤器,在我的回答中我想直接回答 OP 问题所以我不想包含比需要更多的代码
    猜你喜欢
    • 2022-07-01
    • 2019-04-29
    • 2021-06-18
    • 2020-07-05
    • 2020-03-04
    • 2021-12-03
    • 2019-09-28
    • 2020-12-13
    • 2019-09-22
    相关资源
    最近更新 更多