Home > OS >  How to return only 1 (single) record via Django Rest Framework API? (problem with many=False)
How to return only 1 (single) record via Django Rest Framework API? (problem with many=False)

Time:12-17

I have a simple Django Rest Framework API that I would like to return only 1 record. However, when I set many=False, it no longer works. How can I fix this?

Here's the API: (serializer & model below)

class Expense_View_API(APIView):
    permission_classes = [IsAuthenticated, ]

    def get(self, request):

        param_xid = request.GET.get('id','')

        if param_xid != "":
            expenses_recordset = Expenses.objects.filter(xid=param_xid)
            serializer = Expenses_Serializer(expenses_recordset, many=True)
            return Response(serializer.data, status=status.HTTP_200_OK)

        else:
            return Response("BAD REQUEST: Missing 'id' Parameter", status=status.HTTP_400_BAD_REQUEST)

It returns: (good except that I don't want the square list brackets)

[
    {
        "xid": 111,
        "xdate": "2021-02-15T00:00:00Z",
        "xseller": "Amazon",
        "xamount": "30.00",
    }
]

Problem: When I set serializer = Expenses_Serializer(expenses_recordset, many=False), it now returns this null data and drops my xid field. Why?

{
    "xdate": null,
    "xseller": null,
    "xamount": null,
}

I want it to return:

{
    "xid": 111
    "xdate": "2021-02-15T00:00:00Z",
    "xseller": "Amazon",
    "xamount": "30.00",
}

Here's my serializer and data model:

class Expenses_Serializer(serializers.ModelSerializer):

    class Meta:
        model = Expenses
        fields = ('xid', 'xdate', 'xseller', 'xamount')


class Expenses(models.Model):
    xid = models.AutoField(db_column='xID', primary_key=True)  # Field name made lowercase.
    xdate = models.DateTimeField(db_column='xDate', blank=True, null=True)  # Field name made lowercase.
    xseller = models.CharField(db_column='xSeller', max_length=50, blank=True, null=True)  # Field name made lowercase.
    xamount = models.DecimalField(db_column='xAmount', max_digits=19, decimal_places=2, blank=True, null=True)  # Field name made lowercase.

    # Metadata
    class Meta:
        managed = False
        db_table = 'Expenses'
        app_label  = 'Expenses'

    # Methods
    def get_absolute_url(self):
        """Returns the url to access a particular instance of MyModelName."""
        return reverse('model-detail-view', args=[str(self.id)])

    def __str__(self):
        """String for representing the MyModelName object (in Admin site etc.)."""
        return self.my_field_name

Thank you for your time!

CodePudding user response:

The problem is that you are serializing a whole QuerySet(list) by using the filter API. Instead, what you want is to serialize a single object instance:

class Expense_View_API(APIView):
    permission_classes = [IsAuthenticated, ]

    def get(self, request):

        param_xid = request.GET.get('id','')

        if param_xid != "":
            expense_recordset = Expenses.objects.get(xid=param_xid)
            serializer = Expenses_Serializer(expense_recordset)
            return Response(serializer.data, status=status.HTTP_200_OK)

        else:
            return Response("BAD REQUEST: Missing 'id' Parameter", status=status.HTTP_400_BAD_REQUEST)

Also, I recommend the use of get_object_or_404 shortcut, to clean up your view.

  • Related