简体   繁体   中英

Django REST Framework nested serializer FK creation

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.

Can you try with this:

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

    class Meta:
        depth = 2
        model = Employee

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM