带有分页的Django API列表 - 页面不可序列化



我正在尝试创建一个带有分页的列表的DJANGO API,但具有此错误

TypeError: Object of type 'Page' is not JSON serializable

以下是我的API代码:

@api_view(['POST'])
def employee_get_list_by_page(request):
    # ----- YAML below for Swagger -----
    """
    description: employee_get_list_by_page
    parameters:
      - name: token
        type: string
        required: true
        location: form       
      - name: page
        type: string
        required: true
        location: form   
      - name: page_limit
        type: string
        required: true
        location: form                   
    """
    token = request.POST['token']
    try:  
        auth_employee = AuthEmployeeSessionToken.objects.get(token=token) 
    except AuthEmployeeSessionToken.DoesNotExist:   
        return Response("Invalid Token", status=status.HTTP_406_NOT_ACCEPTABLE)
    employee_list = Employee.objects.filter(company = auth_employee.employee.company.id) 

    page = request.GET.get('page', request.POST['page'])
    paginator = Paginator(employee_list, request.POST['page_limit'])
    try:
        employees = paginator.page(page)
    except PageNotAnInteger:
        employees = paginator.page(request.POST['page'])
    except EmptyPage:
        employees = paginator.page(paginator.num_pages)
    return Response(employees,status=status.HTTP_200_OK) <-- passing employees probably cause this error that employees as Page is not JSON serializable.

这是我的模型https://gist.github.com/axilaris/89b2ac6a7762f428ad715f4916f43967。AS_DICT注意,我有此.AS_DICT()创建我的JSON以进行响应。我将其用于单个请求,但对于列表,我不确定它是如何完成的。

  1. 与分页支持的API查询如何?
  2. 我希望JSON仅列出我想要的字段的附带问题。

我刚刚重新创建此问题,我看到了几种修复它的方法。

首先,JSON将无法解析page.object_list属性下面的页面对象或QUERYSET。它会说 "Object of type 'Employee' is not JSON serialisable"

为了解决这个问题,我会尝试:

employee_list = Employee.objects.filter(company = auth_employee.employee.company.id).values().order_by('id') 
page = request.GET.get('page', request.POST['page'])
paginator = Paginator(employee_list, request.POST['page_limit'])
try:
    employees = paginator.page(page)
except PageNotAnInteger:
    employees = paginator.page(request.POST['page'])
except EmptyPage:
    employees = paginator.page(paginator.num_pages)
return Response(list(employees) ,status=status.HTTP_200_OK)

首先,我们在员工QuerySet上使用.values(),因为可以使用list(employees)来解析此调用的结果Quereteryset。在页面类中,他们在返回任何结果之前先评估实例中的对象列表。

最后,由于JSON无法序列化页面类,我们只需调用list(Page)返回列表即可。这是因为页面实现__getitem__并返回基础object_list。

另外,您可能会发现某些数据类型会抛出JSON序列化错误(values()将返回DateTime字段的DateTime对象)。在我的测试中,我对Object of type 'datetime' is not JSON serializable有问题。如果发生这种情况,则需要使用其他JSON编码器或扩展自己的。可以在django.core.core.serializers.json.djangojsonencoder中找到djangojsonencoder,并在Django中处理数据,UUID,小数和其他常见数据类型。

edit ::您已经提到了模型代码为:

class Employee(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='employee')
    company = models.ForeignKey(Company)
    username = models.CharField(max_length=30, blank=False)
    email = models.CharField(max_length=30, blank=False)
    first_name = models.CharField(max_length=30, blank=False)
    last_name = models.CharField(max_length=30, blank=False)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    def __str__(self):
        return self.user.username
    def as_dict(self):
        return {"id": "%d" % self.id,
                "company": self.company.as_dict(),
                "username": self.username if self.username else "",
                "email": self.email if self.email else "",
                "first_name": self.first_name if self.first_name else "",
                "last_name": self.last_name if self.last_name else "",
                "tel":self.tel if self.tel else "",               
                "created_at":self.created_at.strftime('%Y-%m-%d %H:%M'),
                "updated_at":self.updated_at.strftime('%Y-%m-%d %H:%M')}

由于您具有此as_dict方法,因此我们可以使用它来渲染员工的表示,而不是依靠.values()。这是:

employee_list = Employee.objects.filter(company = auth_employee.employee.company.id).order_by('id') 
page = request.GET.get('page', request.POST['page'])
paginator = Paginator(employee_list, request.POST['page_limit'])
try:
    employees = paginator.page(page)
except PageNotAnInteger:
    employees = paginator.page(request.POST['page'])
except EmptyPage:
    employees = paginator.page(paginator.num_pages)
#  Here we map a lambda function over the queryset of Models to return the dictionary representation for each element in the list
employees_page = list(
    map(lambda employee: employee.as_dict(), list(employees))
)
return Response(employees_page ,status=status.HTTP_200_OK)

如果有人使用Django Rest Framework(DRF)找到了这一点,则DRF序列化器可以将page.object_list序列化为JSON。当然,更好的方法是在DRF视图(SET)中指定pagination_class:https://www.django-rest-framework.org/api-guide/pagination/pagination/

最新更新