在 Django Rest Framework 中正确更新嵌套序列化程序

Posted

技术标签:

【中文标题】在 Django Rest Framework 中正确更新嵌套序列化程序【英文标题】:Update Nested Serializers Correctly in Django Rest Framework 【发布时间】:2018-10-26 04:16:22 【问题描述】:

我正在使用django rest framework 我正在尝试对嵌套序列化程序实现更新方法。如何正确实现嵌套序列化程序的更新方法?

我正在尝试更新现有员工,但收到以下回复:


    "user": 
        "username": [
            "A user with that username already exists."
        ]
    

我在序列化程序上实现了一个更新方法,只是为了更新用户字段。

class EmployeeUpdateSerializer(serializers.ModelSerializer):
    user = UserSerializer()
    contract_type = ContractSerializer(read_only=True)
    company = CompanySerializer(read_only=True)
    job_title = JobSerializer(read_only=True)
    department = DepartmentSerializer(read_only=True)
    skill = SkillSerializer(read_only=True)
    unit = UnitSerializer(read_only=True)

    class Meta:
        model = Employee
        fields = ['id', 'user', 'hr_number', 'nssf_no', 'nhif_no', 'induction_date',
                  'induction_date', 'contract_type', 'company',
                  'tax_id_number', 'joining_date', 'job_title', 'skill', 'unit',
                  'department', 'identification_number', 'is_manager', 'active']

    def update(self, instance, validated_data):
        user = validated_data.get('user')
        instance.user.first_name = user.get('first_name')
        instance.user.save()

        return instance

然后在视图中我实现了以下内容:

class EmployeeDetailView(APIView):
    permission_classes = [AllowAny]
    # queryset = Employee.objects.all()
    serializer_class = EmployeeUpdateSerializer
    """
    Retrieve, update or delete a employee instance.
    """

    def get(self, request, pk, format=None):
        try:
            employee = Employee.objects.get(pk=pk)
        except Employee.DoesNotExist:
            raise Http404
        serializer = EmployeeUpdateSerializer(employee)
        return Response(serializer.data, status=status.HTTP_200_OK)

    def put(self, request, pk, format=None):
        try:
            employee = Employee.objects.get(pk=pk)
            serializer = EmployeeUpdateSerializer(
                employee, data=request.data)
        except Employee.DoesNotExist:
            raise Http404
        # serializer = EmployeeUpdateSerializer(data=request.data)
        if serializer.is_valid():
            print(serializer.data)
            serializer.update()
        else:
            return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
        return Response(serializer.data, status=status.HTTP_200_OK)

【问题讨论】:

你试过 patch 而不是 put 吗?因为 put 只是更新所有内容 我已经尝试了补丁,但我得到了相同的结果。 您是否尝试过创建验证?例如,您可以在更新时验证用户的用户名,如果用户名不同则更新它,如果相同则通过? 我认为这行得通 【参考方案1】:

UserSerializer 中用户名字段上的 UniqueValidator 导致了这个问题,它正在对查询集运行验证以检查用户名是否已经存在。

您可以通过将以下内容添加到 Meta 类中来删除 UserSerializer 中的此验证:

        extra_kwargs = 
        'username': 
            'validators': [],
        ,
    

这是一个快速而肮脏的修复,因为如果您尝试使用相同的用户名保存 2 个实例,它将导致您的数据库出现完整性问题。

【讨论】:

以上是关于在 Django Rest Framework 中正确更新嵌套序列化程序的主要内容,如果未能解决你的问题,请参考以下文章

django使用rest_framework

Django Rest Framework

Django rest framework 身份和权限验证

Django Rest Framework:非模型服务

django-rest-framework - 在可浏览的 API 中自动生成表单?

在 django-rest-framework 中,是不是可以同时使用 oauth 和 session 身份验证?