PUT 和 PATCH 上的 Django Rest Framework returns 302 并且不更新任何内容
Django Rest Framework returns 302 on PUT and PATCH and doesn't update anything
我编写了应该更新模型对象实例的序列化程序和视图。
当我通过 THe Django Rest Browsable API 测试 API 时,该过程工作正常,但当我使用 curl 时却没有。 curl 请求(GET、PATCH 和 PUT)在服务器上显示 302,当方法为 patch 时没有任何更新:
curl 命令是:
curl -X PATCH -H "Content-Type: application/json" -d '{ "status": "undefined", "started_at": "2022-03-31T08:22:54"}' http://localhost:8000/wf/machineworks/b79ac69b-e9a6-410b-bfbd-a79b0163f69a
并且,对于 curl 命令,服务器给出:
[31/Mar/2020 12:50:33] "PATCH /wf/machineworks/b79ac69b-e9a6-410b-bfbd-a79b0163f69a HTTP/1.1" 302 0
而可浏览 api 中的相同更新给出:
[31/Mar/2020 13:20:25] "PATCH /fr/wf/machineworks/b79ac69b-e9a6-410b-bfbd-a79b0163f69a/ HTTP/1.1" 200 12588
__ here is the curl log :__
== Info: Trying 127.0.0.1...
== Info: TCP_NODELAY set
== Info: Connected to localhost (127.0.0.1) port 8000 (#0)
=> Send header, 184 bytes (0xb8)
0000: PATCH /wf/machineworks/b79ac69b-e9a6-410b-bfbd-a79b0163f69a HTTP
0040: /1.1
0046: Host: localhost:8000
005c: User-Agent: curl/7.58.0
0075: Accept: */*
0082: Content-Type: application/json
00a2: Content-Length: 61
00b6:
=> Send data, 61 bytes (0x3d)
0000: { "status": "undefined", "started_at": "2022-03-31T08:22:54"}
== Info: upload completely sent off: 61 out of 61 bytes
<= Recv header, 20 bytes (0x14)
0000: HTTP/1.1 302 Found
<= Recv header, 37 bytes (0x25)
0000: Date: Tue, 31 Mar 2020 11:13:27 GMT
<= Recv header, 38 bytes (0x26)
0000: Server: WSGIServer/0.2 CPython/3.6.9
<= Recv header, 40 bytes (0x28)
0000: Content-Type: text/html; charset=utf-8
<= Recv header, 69 bytes (0x45)
0000: Location: /en/wf/machineworks/b79ac69b-e9a6-410b-bfbd-a79b0163f6
0040: 9a/
<= Recv header, 14 bytes (0xe)
0000: Vary: Cookie
<= Recv header, 33 bytes (0x21)
0000: X-Content-Type-Options: nosniff
<= Recv header, 19 bytes (0x13)
0000: Connection: close
<= Recv header, 2 bytes (0x2)
0000:
<= Recv data, 0 bytes (0x0)
== Info: Closing connection 0
查看:
class MachineWorkViewset(viewsets.ViewSet):
"""
A simple ViewSet for listing or retrieving machineworks.
"""
def get_queryset(self,pk=None):
if pk:
return get_object_or_404(MachineWork, pk=pk)
else:
return MachineWork.objects.all()
def list(self, request):
queryset = self.get_queryset()
serializer = MachineWorkSerializer(queryset, many=True)
return Response(serializer.data)
def retrieve(self, request, pk):
queryset = self.get_queryset(pk)
serializer = MachineWorkSerializer(queryset)
return Response(serializer.data)
def update(self, request, pk):
queryset = self.get_queryset(pk)
serializer = MachineWorkSerializer(queryset, data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data)
def partial_update(self, request, pk):
queryset = self.get_queryset(pk)
serializer = MachineWorkSerializer(queryset, data=request.data, partial=True)
if serializer.is_valid():
serializer.save()
return Response(serializer.data)
序列化器
class MachineWorkSerializer(serializers.Serializer):
uuid = serializers.ReadOnlyField(source='id')
task = serializers.CharField(required=False, allow_blank=True, max_length=10)
status = serializers.CharField(required=False, allow_blank=True, max_length=10)
language = serializers.ReadOnlyField(source='language.language')
source = serializers.ReadOnlyField(source='spotler.transcription')
started_at = serializers.DateTimeField()
ended_at = serializers.DateTimeField()
class Meta:
model = MachineWork
def __init__(self, *args, **kwargs):
super(MachineWorkSerializer,self).__init__(*args,**kwargs)
def update(self, instance, validated_data):
"""
Update and return an existing `Snippet` instance, given the validated data.
"""
instance.status = validated_data.get('status', instance.status)
instance.started_at = validated_data.get('started_at', instance.started_at)
instance.ended_at = validated_data.get('ended_at', instance.ended_at)
instance.save()
return instance
型号
class MachineWork(models.Model):
'''
'''
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
spotler = models.ForeignKey(Spotler,on_delete=models.CASCADE,verbose_name = _('Spotler'), related_name='machineworks')
task = models.CharField(max_length=10, choices=TASKS, verbose_name = _('task'), blank=True)
created_at = models.DateTimeField(default=timezone.now, verbose_name = _('submited at'))
started_at = models.DateTimeField(auto_now_add=False, verbose_name = _('started at'), null=True)
ended_at = models.DateTimeField(auto_now_add=False , verbose_name = _('ended at'), null=True)
language = models.ForeignKey(Language,on_delete=models.SET_NULL,verbose_name = _('language'), related_name='machineworks', null=True)
status = models.CharField(max_length=10, choices=STATUS, default='unknown', verbose_name = _('status'), blank=True)
class Meta:
verbose_name = _('Machine Works')
verbose_name_plural = _('Machine Works')
indexes = [models.Index(fields=['spotler','language']),]
def stop(self, status='done'):
self.ended_at = timezone.now()
self.status = status
self.save()
self.spotler.sequencer.refresh()
def save(self,*args,**kwargs):
super(MachineWork,self).save(*args,**kwargs)
self.spotler.sequencer.update(self)
我看到了很多与此问题相近的问题,但我没有找到任何有效的答案...看起来很简单,但我很迷茫...
您看到的重定向来自您的 i18n 设置:您正在向 /wf/...
提交 PUT 或 PATCH 请求,Django 重定向到 /en/wf/...
。
302 重定向总是会产生后续的 GET 请求,这就是为什么您看不到任何错误但也没有保存任何内容的原因。
所以要么:
- 将您的请求提交给 API,在 URL 前加上语言 (
/en/wf/...
)
- 或为您的 API 网址禁用 URL 语言前缀。
您可以通过不在您的网址配置中的 i18n_patterns
中包含您的 API 网址来执行后者。
我编写了应该更新模型对象实例的序列化程序和视图。 当我通过 THe Django Rest Browsable API 测试 API 时,该过程工作正常,但当我使用 curl 时却没有。 curl 请求(GET、PATCH 和 PUT)在服务器上显示 302,当方法为 patch 时没有任何更新:
curl 命令是:
curl -X PATCH -H "Content-Type: application/json" -d '{ "status": "undefined", "started_at": "2022-03-31T08:22:54"}' http://localhost:8000/wf/machineworks/b79ac69b-e9a6-410b-bfbd-a79b0163f69a
并且,对于 curl 命令,服务器给出:
[31/Mar/2020 12:50:33] "PATCH /wf/machineworks/b79ac69b-e9a6-410b-bfbd-a79b0163f69a HTTP/1.1" 302 0
而可浏览 api 中的相同更新给出:
[31/Mar/2020 13:20:25] "PATCH /fr/wf/machineworks/b79ac69b-e9a6-410b-bfbd-a79b0163f69a/ HTTP/1.1" 200 12588
__ here is the curl log :__
== Info: Trying 127.0.0.1...
== Info: TCP_NODELAY set
== Info: Connected to localhost (127.0.0.1) port 8000 (#0)
=> Send header, 184 bytes (0xb8)
0000: PATCH /wf/machineworks/b79ac69b-e9a6-410b-bfbd-a79b0163f69a HTTP
0040: /1.1
0046: Host: localhost:8000
005c: User-Agent: curl/7.58.0
0075: Accept: */*
0082: Content-Type: application/json
00a2: Content-Length: 61
00b6:
=> Send data, 61 bytes (0x3d)
0000: { "status": "undefined", "started_at": "2022-03-31T08:22:54"}
== Info: upload completely sent off: 61 out of 61 bytes
<= Recv header, 20 bytes (0x14)
0000: HTTP/1.1 302 Found
<= Recv header, 37 bytes (0x25)
0000: Date: Tue, 31 Mar 2020 11:13:27 GMT
<= Recv header, 38 bytes (0x26)
0000: Server: WSGIServer/0.2 CPython/3.6.9
<= Recv header, 40 bytes (0x28)
0000: Content-Type: text/html; charset=utf-8
<= Recv header, 69 bytes (0x45)
0000: Location: /en/wf/machineworks/b79ac69b-e9a6-410b-bfbd-a79b0163f6
0040: 9a/
<= Recv header, 14 bytes (0xe)
0000: Vary: Cookie
<= Recv header, 33 bytes (0x21)
0000: X-Content-Type-Options: nosniff
<= Recv header, 19 bytes (0x13)
0000: Connection: close
<= Recv header, 2 bytes (0x2)
0000:
<= Recv data, 0 bytes (0x0)
== Info: Closing connection 0
查看:
class MachineWorkViewset(viewsets.ViewSet):
"""
A simple ViewSet for listing or retrieving machineworks.
"""
def get_queryset(self,pk=None):
if pk:
return get_object_or_404(MachineWork, pk=pk)
else:
return MachineWork.objects.all()
def list(self, request):
queryset = self.get_queryset()
serializer = MachineWorkSerializer(queryset, many=True)
return Response(serializer.data)
def retrieve(self, request, pk):
queryset = self.get_queryset(pk)
serializer = MachineWorkSerializer(queryset)
return Response(serializer.data)
def update(self, request, pk):
queryset = self.get_queryset(pk)
serializer = MachineWorkSerializer(queryset, data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data)
def partial_update(self, request, pk):
queryset = self.get_queryset(pk)
serializer = MachineWorkSerializer(queryset, data=request.data, partial=True)
if serializer.is_valid():
serializer.save()
return Response(serializer.data)
序列化器
class MachineWorkSerializer(serializers.Serializer):
uuid = serializers.ReadOnlyField(source='id')
task = serializers.CharField(required=False, allow_blank=True, max_length=10)
status = serializers.CharField(required=False, allow_blank=True, max_length=10)
language = serializers.ReadOnlyField(source='language.language')
source = serializers.ReadOnlyField(source='spotler.transcription')
started_at = serializers.DateTimeField()
ended_at = serializers.DateTimeField()
class Meta:
model = MachineWork
def __init__(self, *args, **kwargs):
super(MachineWorkSerializer,self).__init__(*args,**kwargs)
def update(self, instance, validated_data):
"""
Update and return an existing `Snippet` instance, given the validated data.
"""
instance.status = validated_data.get('status', instance.status)
instance.started_at = validated_data.get('started_at', instance.started_at)
instance.ended_at = validated_data.get('ended_at', instance.ended_at)
instance.save()
return instance
型号
class MachineWork(models.Model):
'''
'''
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
spotler = models.ForeignKey(Spotler,on_delete=models.CASCADE,verbose_name = _('Spotler'), related_name='machineworks')
task = models.CharField(max_length=10, choices=TASKS, verbose_name = _('task'), blank=True)
created_at = models.DateTimeField(default=timezone.now, verbose_name = _('submited at'))
started_at = models.DateTimeField(auto_now_add=False, verbose_name = _('started at'), null=True)
ended_at = models.DateTimeField(auto_now_add=False , verbose_name = _('ended at'), null=True)
language = models.ForeignKey(Language,on_delete=models.SET_NULL,verbose_name = _('language'), related_name='machineworks', null=True)
status = models.CharField(max_length=10, choices=STATUS, default='unknown', verbose_name = _('status'), blank=True)
class Meta:
verbose_name = _('Machine Works')
verbose_name_plural = _('Machine Works')
indexes = [models.Index(fields=['spotler','language']),]
def stop(self, status='done'):
self.ended_at = timezone.now()
self.status = status
self.save()
self.spotler.sequencer.refresh()
def save(self,*args,**kwargs):
super(MachineWork,self).save(*args,**kwargs)
self.spotler.sequencer.update(self)
我看到了很多与此问题相近的问题,但我没有找到任何有效的答案...看起来很简单,但我很迷茫...
您看到的重定向来自您的 i18n 设置:您正在向 /wf/...
提交 PUT 或 PATCH 请求,Django 重定向到 /en/wf/...
。
302 重定向总是会产生后续的 GET 请求,这就是为什么您看不到任何错误但也没有保存任何内容的原因。
所以要么:
- 将您的请求提交给 API,在 URL 前加上语言 (
/en/wf/...
) - 或为您的 API 网址禁用 URL 语言前缀。
您可以通过不在您的网址配置中的 i18n_patterns
中包含您的 API 网址来执行后者。