2

我在 django rest 框架中使用以下代码来实现 put 和 patch 功能。PATCH (partial_update) 工作正常,但是,为 PUT 提供更少的字段不会像 PUT 请求那样替换整个资源。例如,如果数据如下所示:

{
"id": 6,
"name": "crticial MVP",
"description": "getting things done",
"end": "2012-02-18"   
}

如果我尝试使用以下数据进行 PUT(在http://localhost:800/api/sprints/6/上):

{
    "name": "critical MVP2", 
    "end": "2012-02-18"
}

此调用应将描述设置为无。但是描述保留了它的价值,就好像我在做一个补丁一样。如何在更新功能中强制执行资源替换?

PS:我在初始化序列化程序以进行更新时设置了 partial=False。

视图.py:

class SprintViewSet(viewsets.ModelViewSet):
    queryset = Sprint.objects.order_by('end')
    serializer_class = SprintSerializer 
    def update(self, request, *args, **kwargs):
        sprint=self.get_object()                        
        serializer = SprintSerializer(sprint, data=request.data, partial=False,
 context={'request': request, 'view':self, 'format':None})
        serializer.is_valid(raise_exception=True)       
        serializer.save()
        return Response(serializer.data)
    def partial_update(self, request, *args, **kwargs):
        instance = self.get_object()
        serializer = SprintSerializer(instance, data=request.data, partial=True,
 context={'request': request, 'view':self, 'format':None})
        serializer.is_valid(raise_exception=True)
        new_instance = serializer.save()
        return Response(serializer.data)

序列化程序.py:

class SprintSerializer(serializers.ModelSerializer):
    links = serializers.SerializerMethodField()
    class Meta:     
        model = Sprint              
        fields = ('id', 'name', 'description', 'end', 'links')
    def get_links(self, obj):
        request = self.context['request'] 
        return {
                'self': reverse('sprint-detail',
                kwargs={'pk': obj.pk},request=request),
                }

模型.py

class Sprint(models.Model): 
    name = models.CharField(max_length=100, blank=True, default='')
    description = models.TextField(blank=True, default='')
    end = models.DateField(unique=True)
    def __str__(self):
        return self.name or _('Sprint ending %s') % self.end
4

1 回答 1

5

APUT期望传入完整的数据对象,因此模型上的任何属性都将替换为传入的数据。但这需要传入完整的数据对象,因此如果您不传入字段,则根据数据的发送方式,它将被忽略。

如果您使用表单数据(没有 JSON 的 AJAX 或 HTML <form>)发送数据,则该字段将被完全忽略。这主要与某些浏览器在未设置该值时不发送某些字段(例如复选框)有关,因此 DRF 在这些情况下手动覆盖它。

如果您使用 JSON 并且不需要该字段(这似乎是您的情况),则 DRF 只会在将密钥传递到请求中时覆盖该值。PUT这是因为 a应该包含一个完整的数据对象,而 DRF 基于此做了一些假设。

于 2015-03-31T21:09:13.753 回答