«Неверные данные. Ожидал словарь, но получил сериализатор метакласса». — Сериализаторы DRF

#django-models #django-rest-framework #django-views #django-serializer

Вопрос:

Я пытаюсь создать приложение для обмена сообщениями с помощью django-rest-фреймворка. На мой взгляд, у меня возникла проблема при возврате ответа. С текущим кодом, показанным выше, когда я размещаю запрос get, я получаю:

 {
    "non_field_errors": [
        "Invalid data. Expected a dictionary, but got SerializerMetaclass."
    ]
}    
 

Немного дополнительной информации…
Я думаю, что ошибка как-то связана с моим множеством полей в моей модели общения, но я могу ошибаться.

Поле участники в моей модели общения имеет отношение «многие ко многим» к пользователям. (В разговоре может быть 2 пользователя, но у пользователя может быть любое количество разговоров)

 class Message(models.Model):

    message_id = models.AutoField(primary_key=True)
    conversation_id = models.ForeignKey(to=Conversation, null=False, blank=False, on_delete=models.CASCADE)
    message_body = models.TextField(null=False) 
    sender_id = models.ForeignKey(to=User,to_field='id', on_delete=models.CASCADE)
    sent_date = models.CharField(max_length=400, null=True)
    created_at = models.DateTimeField(auto_now_add=True, null=True)

    class Meta:
        ordering = ['-created_at']

    def __str__(self):
        return str(self.message_id)   
 
 class Conversation(models.Model):
    conversation_id = models.AutoField(primary_key=True)
    participants = models.ManyToManyField(to=User)
    created_at = models.DateTimeField(auto_now_add=True, null=True)


    class Meta:
        ordering = ['-created_at']

    def __str__(self):
        convo_id = self.conversation_id
        return 'Conversation '   str(convo_id)
 
 class ConversationSerializer(serializers.ModelSerializer): 

    other_username = serializers.CharField(read_only=True)
    other_user_email = serializers.CharField(read_only=True)
    latest_message = serializers.CharField(read_only=True)
    participants = UsersSerializer(many=True, read_only=True)


    class Meta:
        model = Conversation
        fields = ['conversation_id', 'participants','other_username','other_user_email','latest_message']

    def get_current_user(self, obj):
        request = self.context.get('request',None)
        if request == None:
            raise ValueError('No request object')
        return request.user    

    def get_other_user_id(self, current_user_id, participants):
        for id in participants:
            if current_user_id != id:
                return id
    
    def get_latest_message(self, conversation_id):
        
        latest_message = Message.objects.filter(conversation_id=conversation_id).latest()
        message_body = latest_message.message_body
        sent_date = latest_message.sent_date

        latest_message = {
            'message_body': message_body,
            'sent_date': sent_date,
            'is_read': True
        }
        return latest_message


    def validate(self, data):
        conversation_id = data.get('conversation_id')
        participants = data.get('participants', ' ')
        current_user = self.get_current_user()
        current_user_id = current_user.id
        other_user_id = self.get_other_user_id(current_user_id=current_user_id,participants=participants)
        latest_message = self.get_latest_message()

        other_user = User.objects.get(id=other_user_id)
        other_username = other_user.username
        other_user_email = other_user.email

        if other_user is None:
            raise ValidationError('Could not get other user') 

        new_data = {
            'conversation_id': conversation_id,
            'other_username': other_username,
            'other_user_email': other_user_email,
            'latest_message': latest_message,
        }
        return new_data
 
 class GetConversationView(GenericAPIView):
    serializer_class = ConversationSerializer
    authentication_classes = []
    permission_classes = [AllowAny]
    queryset = Conversation.objects.all()

    def get_queryset(self):
        return self.queryset.all()


    def get(self, request):
        queryset = self.get_queryset()
        serializer = self.serializer_class(data=ConversationSerializer)
        if serializer.is_valid():
            return Response(serializer.data, status=status.HTTP_200_OK)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)    
 

Комментарии:

1. serializer = self.serializer_class(data=ConversationSerializer) в этой строке вы передаете сам класс сериализатора для сериализации сериализатора. Похоже, что вы собираетесь передать список Conversation объектов, так что: self.serializer_class(queryset, many=True)

2. Спасибо, я полный идиот. Я проверял свой сериализатор в течение последнего часа, задаваясь вопросом, что происходит. Спасибо за помощь!