Обновление многих объектов в одном запросе DRF

Мне нужно массово обновить ("is_read" = True) Message instanses по заданному списку id в одном запросе с помощью следующего кода:

{"ids": [11, 4, 7]}

Модель:

class Message(models.Model):

text = models.TextField(max_length=500, verbose_name=_("Text"))
sender = models.ForeignKey(
    to=User,
    on_delete=models.CASCADE,
    related_name="sender_message",
    verbose_name=_("User"),
)
thread = models.ForeignKey(
    to="Thread",
    on_delete=models.CASCADE,
    related_name="thread_message",
    verbose_name=_("Thread"),
)
created_at = models.DateTimeField(auto_now_add=True, verbose_name=_("Created"))
updated_at = models.DateTimeField(auto_now=True, verbose_name=_("Updated"))
is_read = models.BooleanField(default=False, verbose_name=_("Is read"))

У меня есть этот сериализатор:

class MessageIsReadSerializer(serializers.ModelSerializer):

    class Meta:

        model = Message
        fields = ("id", "text", "sender", "is_read")

And метод в views.py:

class MessageIsRead(APIView):

permission_classes = (AllowAny,)
queryset = Message.objects.all()

def put(self, request, *args, **kwargs):
    id_list = request.data['ids']
    instances = []
    for item in id_list:
        obj = self.queryset.filter(id=item)
        obj.is_read = True
        instances.append(obj)
    serializer = MessageIsReadSerializer(instances, many=True)
    return Response(serializer.data)

urls.py

urlpatterns = [
    path("messages-read/", MessageIsRead.as_view()),
]

Но в результате выполнения этого запроса я получаю ошибку:

AttributeError at /messages-read/
Got AttributeError when attempting to get a value for field `text` on serializer 
`MessageIsReadSerializer`.
The serializer field might be named incorrectly and not match any attribute or key on the 
`QuerySet` instance.
Original exception text was: 'QuerySet' object has no attribute 'text'.

Что случилось?

Во-первых: здесь вы получаете кверисет, а не экземпляр, поэтому далее в коде вы добавляете кверисет к списку instances. Если вы хотите получить доступ к отдельному экземпляру, вам следует использовать get вместо filter

single_instance = self.queryset.get(id=item)

Если вы хотите обновить несколько элементов, вы можете использовать:

def put(self, request, *args, **kwargs):
    id_list = request.data['ids']

    instances = self.queryset.filter(id__in=id_list).update(is_read=True)
    
    serializer = MessageIsReadSerializer(instances, many=True)
    return Response(serializer.data)
Вернуться на верх