1

I'm in trouble creating a bunch of related models using DRF nested serializers. They are failing validation on the foreign key.

Models

class Employee(models.Model):
    user = models.OneToOneField(User)  # Django user
    ...

class Task(models.Model):
    author = models.ForeignKey(Employee, related_name='tasks')
    title = models.CharField(max_length=64)
    ...

class EmployeeTarget(models.Model):
    employee = models.ForeignKey(Employee, null=False)
    task = models.ForeignKey(Task, null=False, related_name='employee_targets')
    ...

Objective

Basically I have the Employees already created, and I want to create a Task and related EmployeeTarget in a single request, getting the request user as the author. JSON request example:

{
    "title": "Lorem Ipsum",
    "employee_targets": [
         { "employee": 10 },
         { "employee": 11 }]
}
/* or */
{
    "title": "Lorem Ipsum",
    "employee_targets": [10,11]
}

Serializers

class EmployeeSerializer(serializers.ModelSerializer):
    name = serializers.CharField(source="user.get_full_name", read_only=True)
    email = serializers.CharField(source="user.email", read_only=True)

    class Meta:
        model = Employee

class EmployeeTargetSerializer(serializers.ModelSerializer):
    employee = EmployeeSerializer()

    class Meta:
        model = EmployeeTarget

class TaskSerializer(base.ModelSerializer):
    employee_targets = EmployeeTargetSerializer(many=True, required=False)

    class Meta:
        model = Task

    def create(self, validated_data):
        employee_target_data = validated_data.pop('employee_targets')
        task = Task.objects.create(**validated_data)
        EmployeeTarget.objects.create(task=task, **employee_target_data)
        return task

ViewSet

class TaskViewSet(ModelViewSet):

    serializer_class = TaskSerializer

    def get_queryset(self):
        request_employee = self.request.user.employee
        return Task.objects.filter(Q(author=request_employee) |
                                   Q(employee_targets__employee=request_employee))

    def perform_create(self, serializer):
        serializer.save(author=self.request.user.employee)

Result

I'm getting 400 BAD REQUEST with the following error:

{
  "employee_targets": [
    {
      "employee": {
        "non_field_errors": ["Invalid data. Expected a dictionary, but got int."]
      },
      "task": ["This field is required."]
    }
  ],
  "author": ["This field is required."]
}

The employee error was expected, but I haven't figured out how to create them using only the ID.

The bigger problem here is the employee_targets failing validation at the task FK, before the enclosing TaskSerializer specify them at create method.

2

1 Answer 1

1

Can you try with this:

class EmployeeSerializer(serializers.ModelSerializer):
    name = serializers.CharField()
    email = serializers.CharField()

    class Meta:
        depth = 2
        model = Employee
Sign up to request clarification or add additional context in comments.

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.