user2896120
user2896120

Reputation: 3282

Get Old Objects, Update, and then return old objects

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?

Upvotes: 1

Views: 113

Answers (1)

willeM_ Van Onsem
willeM_ Van Onsem

Reputation: 477180

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

Upvotes: 1

Related Questions