Django Rest Framework: загрузка файла через AJAX

У меня есть вид и сериализатор:

class UserView(generics.RetrieveUpdateAPIView):
    model = get_user_model()
    serializer_class = UserProfileSerializer
    permission_classes = (permissions.IsAuthenticated,)

    def get_object(self, *args, **kwargs):
        return self.request.user


class UserImageSerializer(serializers.ModelSerializer):
    class Meta:
        model = get_user_model()
        fields = ('image',)

Они отлично работают с httpie:

http -f put localhost:8000/accounts/api/image/ "Authorization: Token mytoken" image@~/Downloads/test.jpg
HTTP/1.0 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Date: Thu, 03 Sep 2015 22:50:33 GMT
Server: WSGIServer/0.2 CPython/3.4.3
Vary: Accept
X-Frame-Options: SAMEORIGIN

{
    "image": "http://localhost:8000/media/accounts/user_images/test.jpg"
}

и мое изображение загружено и отображается в админке.

Теперь я хочу иметь возможность загружать файл, используя AJAX, но он явно не хочет работать:

<form action="http://localhost:8000/accounts/api/image/"
      method="put"
      enctype="multipart/form-data">
    <input name="image" type="file">
    <input type="submit">
</form>

<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>

<script>
    $('form').submit(function(e) {
        var formData = new FormData($(this));
        $.ajax({
            url: $(this).attr('action'),
            type: $(this).attr('method'),
            data: formData,
            headers: {'Authorization': 'Token mytoken'},
            cache: false,
            contentType: false,
            processData: false,
            success: function() { alert('it works') },
        });
        e.preventDefault();
    });
</script>

Теперь появляется мое предупреждение "Это работает". Я знаю, что форма отправляется в нужное место, на сервере разработчиков Django я вижу, что он запрашивается как PUT и что он отвечает 200 (тот же ответ, что и с httpie):

[03/Sep/2015 22:47:23] "PUT /accounts/api/image/ HTTP/1.1" 200 77

Но кажется, что файл не загружается, и он не отображается в админке.

У меня нет идей.

1 ответ

Решение

Хорошо, я не могу точно объяснить, почему, но, похоже, var formData = new FormData($(this)); не достаточно одного, это должно быть явно добавлено, потому что причины? Если кто-нибудь может объяснить, пожалуйста, сделайте.

Рабочий код:

<form action="http://localhost:8000/accounts/api/image/"
      method="put"
      enctype="multipart/form-data">
    <input name="image" type="file" id="image">
    <input type="submit">
</form>

<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>

<script>
    $('form').submit(function(e) {
        var formData = new FormData($(this));
        formData.append('image', $('#image')[0].files[0]);
        $.ajax({
            url: $(this).attr('action'),
            type: $(this).attr('method'),
            data: formData,
            headers: {'Authorization': 'Token mytoken'},
            cache: false,
            contentType: false,
            processData: false,
            success: function() { alert('it works') },
        });
        e.preventDefault();
    });
</script>
Другие вопросы по тегам