I have an APIView
that looks like this:
class GetNotifications(ListAPIView):
serializer_class = NotificationSerializer
def get_queryset(self):
notifications = Notification.objects.select_related().filter(user=self.request.user).order_by("-created_at")
Notification.objects.select_for_update().filter(is_read=False, user=self.request.user).update(is_read=True)
return notifications
What I'm trying to do is get all notifications that the user has. These include notifications that have been read and that have been not read yet (hence the is_read field). I'd like to return both the is_read
and the not is_read
notifications.Once those objects are received then an update will happen to change the not read notifications to is read. What this means is that any user who accesses this API through the site will mean that they've read their notifications so we can set is_read=True
...however, my current code returns the objects after updating them. I want to return the old objects prior to updating hence me assigning notifications to the old objects before updating. I believe this is due to lazy loading on Django's part. Is there a way/better way to solve this?
CodePudding user response:
however, my current code returns the objects after updating them. I want to return the old objects prior to updating hence me assigning notifications to the old objects before updating. I believe this is due to lazy loading on Django's part. Is there a way/better way to solve this?
It will still return the updated objects, since the query will, if ever, be evaluated after the update, and hence at that time is_read
will already be set to True
.
You should "materialize" the queryset, so forcing to load it into memory. For example by calling list(…)
on it:
class GetNotifications(ListAPIView):
serializer_class = NotificationSerializer
def get_queryset(self):
notifications = (
Notification.objects.select_related()
.filter(user=self.request.user)
.order_by('-created_at')
)
list(notifications)
Notification.objects.filter(user=self.request.user).update(is_read=True)
return notifications