Django Rest Framework возвращает 302 на PUT и PATCH и ничего не обновляет - PullRequest
0 голосов
/ 31 марта 2020

Я закодировал сериализатор и представления, которые должны обновлять экземпляры объекта модели. Когда я тестирую API с помощью Django Rest Browsable 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)

Я видел много проблем, близких к этому, но я не нашел ответа, который работает ... кажется простым, но я совсем растерялся ...

1 Ответ

2 голосов
/ 31 марта 2020

Перенаправление, которое вы видите, происходит из ваших настроек i18n: вы отправляете запрос PUT или PATCH на /wf/... и Django перенаправляет на /en/wf/....

Перенаправление 302 всегда будет приводить к последующему GET-запросу, поэтому вы не видите ни ошибки, но и почему ничего не сохраняется.

Так что либо:

  • Отправьте запрос в API с префиксом URL на языке (/en/wf/...)
  • Или отключите префикс языка URL для URL-адресов API.

Вы можете сделать последнее, не включая ваши URL-адреса API в i18n_patterns в вашей конфигурации URL.

...