带分页的Django API列表-页面不可JSON序列化 [英] Django API list with pagination - Page is not JSON serializable
问题描述
我正在尝试为带有分页的列表创建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.
- 如何通过分页支持对此列表进行API查询?
- 我希望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屋!