Nursultan Bolatbayev
Nursultan Bolatbayev

Reputation: 148

Get latest object with filter in django rest framework

When I request GET through DRF API, I want to return the latest object. I tried this one in views.py:

class ListCreateNodeConfig(generics.ListCreateAPIView):
    queryset = models.NodeConfig.objects.all()
    serializer_class = serializers.NodeConfigSerializer

    def get_queryset(self):
        return self.queryset.filter(node_id=self.kwargs.get('node_pk')).latest('timestamp')

But it throws error: 'NodeConfig' object is not iterable

models.py

class NodeConfig(models.Model):  
    node_id = models.ForeignKey(Node)
    timestamp = models.DateTimeField(auto_now_add=True, auto_now=False)
    record_interval = models.IntegerField(default=0)
    lower_frequency = models.IntegerField(default=0)
    upper_frequency = models.IntegerField(default=0)

How to fix it?

Any suggestions are appreciated.

Upvotes: 3

Views: 7115

Answers (2)

user3437022
user3437022

Reputation: 97

You could also use python slicing for return single object into queryset:

self
  .queryset
  .filter(node_id=self.kwargs.get('node_pk'))
  .order_by('-timestamp')[:1]

Upvotes: 0

ohrstrom
ohrstrom

Reputation: 2970

The porblem here ist the latest() method. This does not return a queryset but a single model instance. (like get(...))

so use:

def get_queryset(self):
    return self.queryset.filter(node_id=self.kwargs.get('node_pk')).order_by('-timestamp')

So if you want to have an endpoint for a single object you must not use DRF List* views/mixins.
The listviews assume you want to work with lists (=multiple objects). And so they rely on queryset resp. get_queryset. And a queryset should obviously be a queryset and not a model instance...

But there is also the RetrieveAPIView view included:

from rest_framework.generics import RetrieveAPIView

class LatestNodeConfigView(RetrieveAPIView):
    queryset = models.NodeConfig.objects.all()
    # add your serializer
    serializer_class = NodeConfigDetailSerializer

    def get_object(self, *args, **kwargs):
        return self.queryset.filter(node_id=kwargs.get('node_pk')).latest('timestamp')

Upvotes: 9

Related Questions