Search code examples
pythondjangodjango-rest-frameworkdjango-serializer

Getting objects before validating data Django REST


I have to create a new Chat object using this view:

class ChatListCreateView(ListCreateAPIView):
    permission_classes = [IsAuthenticated]
    serializer_class = ChatSerializer

    def get_queryset(self):
        data = Chat.objects.filter(
            Q(employees=self.request.user) | Q(created_by=self.request.user)).distinct()
        return data

The serializer it uses is:

class ChatSerializer(serializers.ModelSerializer):
    created_by = SimpleEmployeeSerializer(read_only=True)
    employees = SimpleEmployeeSerializer(many=True, read_only=True)
    title = serializers.CharField(max_length=255)

    def create(self, validated_data):
        """
        Creates a new Chat and adds the m2m employees to it
        """
        # Create and save the chat
        chat = Chat.objects.create(
            created_by=self.context['request'].user,
            title=validated_data['title'],
        )

        # Add the employees to the chat
        validated_employees = validated_data.pop('employees')
        for user_id in validated_employees:
            employee = Employee.objects.get(id=user_id)
            chat.employees.add(employee)

        return chat

My issue is that the SimpleEmployeeSerializer expects a user object but I am submitting an array of employees as such:

{
    "title": "fwef",
    "employees": [
        {
            "id": "8"
        },
        {
            "id": "30"
        }
    ]
}

What method can I implement to get the objects from these IDs before validation?


Solution

  • I think you need to add the employee_ids field in the serializer.

    class ChatSerializer(serializers.ModelSerializer):
        created_by = SimpleEmployeeSerializer(read_only=True)
        employees = SimpleEmployeeSerializer(many=True, read_only=True)        
        title = serializers.CharField(max_length=255)
        employee_ids = serializers.ListField(
            child=serializers.IntegerField(), write_only=True
        )
    
    def create(self, validated_data):
        """
        Creates a new Chat and adds the m2m employees to it
        """
        employee_ids = validated_data.pop("employee_ids")
    
        # Create and save the chat
        chat = Chat.objects.create(
            created_by=self.context['request'].user,
            title=validated_data['title'],
        )
    
        # Add the employees to the chat one by one
        for user_id in employee_ids:
            try:
                employee = Employee.objects.get(id=user_id)
                chat.employees.add(employee)
            except Employee.DoesNotExist:
                continue
        
        # Or you can add multiple objects at once
        # chat.employees.set(employee_ids)
    
        return chat
    

    And you can upload json data as follows.

    {
        "title": "fwef",
        "employees": [
            8, 30
        ]
    }