Обновление многих объектов в одном запросе 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)