0

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?

2 Answers 2

4

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
    ]
}
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks for the answer! To follow up: does the fact that I have to do this conversion suggest that I am building my business logic incorrectly?
1

Hello David you can take advantage of override the validate method in the serializer you have to do something like the following:

class ChatSerializer(serializers.ModelSerializer):
    created_by = SimpleEmployeeSerializer(read_only=True)
    employees = SimpleEmployeeSerializer(many=True, read_only=True)
    title = serializers.CharField(max_length=255)
    
    def validate_employees(self, value):
        value= transform_ids_in_objects(value) 
        # handle validation logic here 
        return value

    def create(self, validated_data):
        chat = Chat.objects.create(
            created_by=self.context['request'].user,
            title=validated_data['title'],
        )
        # ... More code here
        return chat

Documentation about validate method Something important about validate method is that this method is called before create method.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.