2017-12-06 10 views
1

ではない私は、次のページネーションとのリストについては、DjangoのAPIを作成しようとしているが、このエラーを持っているページネーションとDjangoのAPIリストに - ページはJSONシリアライズ可能な

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 notice私は応答のために私のjsonを作成するこの.as_dict()を持っています。私は単一の要求のためにそれを使用するが、どのように行われているかわからないリストのために。

  1. ページングをサポートしているこのリストのAPIクエリはどのようにして作成されますか?
  2. JSONに必要な項目だけをリストしたいという面倒な問題。

答えて

2

私はちょうどこれを作り直しました。それを修正する方法がいくつかあります。

最初に、JSONはPageオブジェクトまたはpage.object_listプロパティの基礎となるQuerySetのいずれかを解析できません。それは"Object of type 'Employee' is not JSON serialisable"と言います。だから、これを解決する

、私が試してみた:この呼び出しの結果ValuesQuerySetがlist(employees)で解析することができますので、

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()を使用しています。 Pageクラス内では、このようにしてインスタンス内のオブジェクトリストを評価してから結果を返します。

最後に、JSONはPageクラスをシリアル化できないため、単にlist(Page)を呼び出してリストを返します。これは、ページが__getitem__を実装し、基礎となるobject_listを返すために機能します。

また、一部のデータ型でJSONのシリアル化エラーが発生することがあります(values()はDateTimeフィールドのDateTimeオブジェクトを返します)。私のテストでは、Object of type 'datetime' is not JSON serializableに関する問題がありました。このような場合は、別のJSONエンコーダーを使用するか、独自のエンコーダーを拡張する必要があります。 DjangoJSONEncoderは、django.core.serializers.json.DjangoJSONEncoderにあり、djangoのdatetimes、uuids、decimals、およびその他の一般的なデータ型を処理します。あなたはこのas_dictメソッドを持っているので、我々は代わりに.values()に頼るの従業員の表現をレンダリングするためにこれを使用することができ

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')} 

編集::あなたはとあなたのモデルコードを言及しました。方法は次のとおりです。

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) 
+1

私は質問に合格できません。ここにエラーがありますhttps://gist.github.com/axilaris/226ad1e0dde14d96b1be6eb71ddd6e88 – Axil

+1

もう1つのリファレンスを追加しましたhttps://gist.github.com/axilaris/89b2ac6a7762f428ad715f4916f43967私のモデルを設計して、私が望むようなjsonフィールドを表示する方法について。そこから使用できるものは何ですか? – Axil

+0

ねえ、その問題を注文で解決するために私の答えを更新しました。あなたのモデルに基づいて私はあなたのために私の答えを少し広げます。 – ARJMP

関連する問題