首页 > 解决方案 > 使用 fetch api 上传图像在 django 中不起作用

问题描述

我的views.py文件

def change_profile_picture(request):
    if not request.user.is_authenticated:
        return JsonResponse({"status": "403", "msg": "Unauthorized request"})
    if request.method == 'POST':
        if request.is_ajax():
            form = UploadPictureForm(request.POST)
            if form.is_valid():
                customuser = request.user.customuser
                customuser.picture = form.cleaned_data['picture']
                customuser.save()
                return JsonResponse(
                    {
                        "status": "200",
                        "msg": "Successful",
                        "data": f"{customuser.picture.url}"
                    }
                )
            else:
                return JsonResponse({"status": "400", "msg": "invalid form"})
        else:
            return JsonResponse({"status": "401", "msg": "Bad request"})
    else:
        return JsonResponse({"status": "403", "msg": "invalid request method"})

forms.py

class UploadPictureForm(forms.Form):
    picture = forms.ImageField(
        label="Profile picture"
    )

Javascript代码:

function getCookie(name) {
    var cookieValue = null;
    if (document.cookie && document.cookie !== '') {
        var cookies = document.cookie.split(';');
        for (var i = 0; i < cookies.length; i++) {
            var cookie = cookies[i].trim();
            // Does this cookie string begin with the name we want?
            if (cookie.substring(0, name.length + 1) === (name + '=')) {
                cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                break;
            }
        }
    }
    return cookieValue;
}

$('.upload-btn').on('click', () => {
    document.getElementById('id_picture').click();
})
$('.close-btn').on('click', () => {
    document.getElementById('profile-picture').src = $('#profile-picture').data('target');
    document.getElementById('submit-picture').style.visibility = 'hidden';
})
$('#submit-picture').on('click', () => {
    var picture = document.querySelector('input[type="file"]');
    var formData = new FormData();
    formData.append('csrfmiddlewaretoken', getCookie('csrftoken'));
    formData.append('picture', picture.files[0]);
    fetch('/auth/change-profile-picture/', {
        method: 'POST',
        body: formData,
        cache: 'default',
        mode: 'cors',
        credentials: 'include',
        headers: {
            "X-Requested-With": "XMLHttpRequest",
        }
    })
    .then((res) => res.json())
    .then((data) => {
        if(data.status === '200') {
            document.getElementById('profile-picture').src = data.data;
            alert("done");
        } else {
            console.log(data.msg);
        }
    })
    .catch((err) => console.log(err))
})

HTML 模板:

<div class="col-md-6 order-sm-12 my-5">
                                <p class="upload-btn"><i class="fa fa-camera"></i>  Edit profile picture</p>
                                <p class="close-btn"><i class="fas fa-times"></i>  Reset</p>
                                <img class="profile-img" id="profile-picture" data-target="{% if user.customuser.picture %}{{ user.customuser.picture.url }}{% endif %}" src="{% if user.customuser.picture %}{{ user.customuser.picture.url }}{% endif %}" />
                                {% if user == request.user %}
                                    <input id="id_picture" style="visibility:hidden;" name="picture" type="file" accept="image/*" required onchange="document.getElementById('profile-picture').src = window.URL.createObjectURL(this.files[0]);document.getElementById('submit-picture').style.visibility = 'visible';">
                                    <button class="btn vizew-btn w-100 my-3" style="visibility:hidden;" id="submit-picture">Change profile picture</button>
                                {% endif %}
                            </div>

视图函数,change_profile_picture返回invalid form,我不知道为什么。到目前为止,我注意到图片文件实际上并没有使用 fetch api 发送。我也尝试过从使用 Javascript 提交更改为使用普通 HTML 表单标签,它仍然给出相同的错误。将继承的表单类更改为 ModelForm 只会使用默认值填充该字段。我如何解决它?

标签: javascriptjquerydjangopython-3.xfetch

解决方案


我在 change_profile 视图中发现,我用提交的数据初始化表单,我没有request.FILES像这样填充表单:

<code>
 if request.method == 'POST':
        if request.is_ajax():
            form = UploadPictureForm(request.POST, request.FILES)
<more code>

推荐阅读