Загрузка изображения с помощью ajax в приложении django

Я столкнулся с проблемой в приложении django. У меня есть ajax-функция для загрузки одного изображения в модель, но пока что я не смог добиться успеха в своей цели. В основном я получаю файл из Ajax, но когда я пытаюсь отправить его в Django запрос в представлении, результатом является объект None. Позвольте мне опубликовать некоторый код, чтобы быть более ясным:

HTML:

{% for question in questions %}
    <tr>
     <td>{{forloop.counter}}</td>
     <td>{{question.id}}</td>
     <td>{{question}}</td>
     <td>
      <a title="{% trans "Edit Question" %}" class="btn btn-warning btn-sm" href="{% url 'administration:edit_question' pk=question.id %}"><i class="fas fa-edit"></i></a>
      <a title="{% trans "See Details" %}" class="btn btn-primary btn-sm ms-3" href="{% url 'administration:question_details' pk=question.id %}" ><i class="fas fa-eye"></i></a>
      <a title="{% trans "Delete Question" %}" href="{% url 'administration:delete_question' pk=question.id %}" id="delete_question" class="btn btn-sm btn-danger ms-3"><i class="fas fa-trash"></i></a>
      <button title="{% trans "Add Image" %}" class="btn btn-sm btn-success ms-3" data-bs-toggle="modal" data-bs-target="#addImageModal{{question.id}}"><i class="fas fa-file-image"></i></button>
      {% if question.explanation %}
      <a title="{% trans "Edit Explanation" %}" href="{% url 'administration:edit_explanation' pk=question.explanation.id %}" class="btn btn-sm btn-info ms-3"><i class="fas fa-edit"></i></a>
      <button title="{% trans "Add Explanation Image" %}" data-bs-toggle="modal" data-bs-target="#addExplanationImageModal{{question.id}}" data-questionId="{{question.id}}" class="btn btn-sm btn-secondary explanationModals ms-3"><i class="fas fa-plus"></i></button>
      {% else %}
       <a title="{% trans "Add Explanation" %}" href="{% url 'administration:add_explanation' pk=question.id %}" class="btn btn-sm btn-info ms-3"><i class="fas fa-plus"></i></a>
       {% endif %}
      </td>
 {% include 'administration/modals/add_question_image_modal.html' %}
 {% include 'administration/modals/add_explanation_image_modal.html' %}
    </tr>
   {% endfor %}

MODAL:

<div class="modal fade" id="addExplanationImageModal{{question.id}}" tabindex="-1" role="dialog" aria-labelledby="addExplanationImageModalLabel" aria-modal="true" style="display: none;">
<div class="modal-dialog modal-dialog-centered">
    <div class="modal-content">
        <div class="modal-header">
            <h5 class="modal-title">{% trans "Add Explanation Image to Explanation n°" %} {{question.explanation.id}}</h5>
            <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
        </div>
        <div class="modal-body">
            <form action="" id="explanationImageForm{{question.id}}" enctype="multipart/form-data">
                {% csrf_token %}
                <div class="form-group">
                  <label>{% trans "Image" %}</label>
                  <input class="form-control" type="file" name="file" id="explanationPicFile{{question.id}}">
                </div>
                <button type="button" id="addExplanationImage{{question.id}}" class="btn btn-success mt-3"> {% trans "Add Image" %} </button>
                <button type="button" class="btn btn-danger mt-3" data-bs-dismiss="modal">{% trans "Close" %}</button>
            </form>
        </div>
    </div><!-- /.modal-content -->
</div><!-- /.modal-dialog -->

JAVASCRIPT:

let explanationModals = [...document.getElementsByClassName('explanationModals')];
explanationModals.forEach((explanationModal) =>
explanationModal.addEventListener("click", (e) => {
    e.preventDefault();
  var questionId = explanationModal.getAttribute("data-questionId");
  
    $('#addExplanationImage'+questionId).on('click', function(e){
        var file = document.getElementById('explanationPicFile'+questionId).files[0]
    var data = new FormData();
    data.append('file', file);
    data.append('csrfmiddlewaretoken', csrftoken);
        $.ajax({
            type: 'POST',
            url: '/administration/add_ajax_question_explanation_image/' +questionId,
            enctype: 'multipart/form-data',
            data: data,
            cache: false, 
            processData: false,
            contentType: false,
            enctype: 'multipart/form-data',
            success: function(res){
                console.log(res)
                console.log(data.get('file'))
            }, 
            error: function(err){
                console.log(err)
            },
        })
    })
})

);

views.py

def add_ajax_question_explanation_image(request, pk):
    question = Question.objects.get(id=pk)
    explanation = Explanation.objects.get(question=question)
    if request.headers.get('x-requested-with') == 'XMLHttpRequest':
        file = request.FILES.get('file')
        image = ExplanationImage(image=file, explanation=explanation)
        image.save()
        return HttpResponse(image)

Представление возвращается правильно, но файл НЕ передается внутри объекта image. Если я печатаю файл, то возвращается None

Вам нужно изменить функцию, чтобы вы могли отправить форму отправки. В вашем коде, вы не отправляете код. для этого, вам нужно изменить форму ниже

<form action="/administration/add_ajax_question_explanation_image/{{question.id}}" enctype="multipart/form-data" class="ajax">
    {% csrf_token %}
    <div class="form-group">
        <label>{% trans "Image" %}</label>
        <input class="form-control" type="file" name="file" id="explanationPicFile{{question.id}}">
    </div>
    <button type="submit"  class="btn btn-success mt-3"> {% trans "Add Image" %} </button>
    <button type="button" class="btn btn-danger mt-3" data-bs-dismiss="modal">{% trans "Close" %}</button>
</form>

выше я добавил URL, изменил тип кнопки на 'submit' и добавил класс ajax. теперь при отправке формы мы можем отправлять данные с помощью ajax

$(document).on('submit', 'form.ajax', function (e) {
        e.preventDefault();
        var url = $this.attr('action');
        data = new FormData(this)
        jQuery.ajax({
            type: method,
            url: url,
            dataType: 'json',
            data: data,
            cache: false,
            contentType: false,
            processData: false,
            success: function (data) {
                // your code here
            }
        })
    });
Вернуться на верх