带分页的Django API列表-页面不可JSON序列化 [英] Django API list with pagination - Page is not JSON serializable

查看:145
本文介绍了带分页的Django API列表-页面不可JSON序列化的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试为带有分页的列表创建Django API,但是出现此错误

I am trying to create a Django API for a list with pagination but have this error

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

以下是我的API代码:

The following is my API code:

@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进行响应.我将其用于单个请求,但用于列表,我不确定它是如何完成的.

This is my model https://gist.github.com/axilaris/89b2ac6a7762f428ad715f4916f43967. as_dict notice I have this .as_dict() to create my json for response. I use it for single request but for list Im not sure how it is done.

  1. 如何通过分页支持对此列表进行API查询?
  2. 我希望JSON仅列出所需字段的侧面问题.

推荐答案

我只是想重新创建它,所以我看到了一些解决方法.

I just had a go at recreating this, and I see a few ways to fix it.

首先,JSON将无法解析Page对象或page.object_list属性基础的QuerySet.会显示"Object of type 'Employee' is not JSON serialisable".

Firstly, JSON will not be able to parse either the Page object, nor the QuerySet underlying the page.object_list property. It will say "Object of type 'Employee' is not JSON serialisable".

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

So to solve this, I'd try:

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)

首先,我们在雇员查询集上使用.values(),因为此调用的结果ValuesQuerySet可以使用list(employees)进行解析.在Page类内部,他们以这种方式评估实例内部的对象列表,然后返回任何结果.

Firstly, we use .values() on the employees queryset because the resulting ValuesQuerySet of this call can be parsed with list(employees). Inside the Page class, they evaluate the object list inside the instance this way before returning any results.

最后,由于JSON无法序列化Page类,因此我们只需调用list(Page)以返回列表.之所以可行,是因为Page实现__getitem__并返回基础的object_list.

Lastly, because JSON can't serialise the Page class, we simply call list(Page) to return a list. This works because Page implements __getitem__ and returns the underlying object_list.

此外,您可能会发现某些数据类型将引发JSON序列化错误(values()将为DateTime字段返回DateTime对象).在我的测试中,我遇到了Object of type 'datetime' is not JSON serializable的问题.如果发生这种情况,则需要使用其他JSON编码器或扩展自己的JSON编码器. DjangoJSONEncoder可以在django.core.serializers.json.DjangoJSONEncoder中找到,并处理django中的日期时间,uuid,十进制和其他常见数据类型.

Also, you may find that some datatypes will throw JSON serialization errors (values() will return DateTime objects for DateTime fields). In my testing I had an issue with Object of type 'datetime' is not JSON serializable. If this happens, you need to use a different JSON Encoder or extend your own. The DjangoJSONEncoder can be found in django.core.serializers.json.DjangoJSONEncoder and handles datetimes, uuids, decimals, and other common datatypes in django.

:您提到的模型代码为:

: You've mentioned your model code as:

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().方法如下:

Because you have this as_dict method, we could use this to render the representation of your employees instead of relying on .values(). Here is how:

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 API列表-页面不可JSON序列化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆