首页 > 解决方案 > 如何将ajax添加到django网页

问题描述

我正在开发一个 django 应用程序。此应用程序有两种形式。在第一个表单 ( image_form ) 中,用户可以上传图像。在第二种形式(image_description)中,用户可以填写一些关于图像的描述。当图像以第一种形式上传时,图像上运行的图像分类器会尝试填充 image_description 表单的部分内容。提交第二个表单后,该项目将显示在新页面 ( item_list ) 中。这是应用程序的 urlpatterns。

网址.py

urlpatterns = [
    path('', views.index, name='home'),
    path('accounts/', include('django.contrib.auth.urls')),

    path('signup/', views.signup, name='signup'),

    path('items/', views.item_list, name='item_list'),
    path('items/upload/description/', views.upload_item, name='upload_item'),
    path('items/<int:pk>/', views.delete_item, name='delete_item'),
    path('items/upload/image_classification/', views.image_classification, name='image_classification'),
]

这里的item_list是显示所有项目的页面。提交 image_description 表单后,将显示此页面。

upload_item页面包含这两种形式。

image_classification在第一个表单中的上传图片按钮被点击时运行。这发生在 upload_item 页面中。

视图.py

def item_list(request):
    items = Item.objects.all()

    return render(request, 'item_list.html', {'items':items})

def upload_item(request):
    if request.method == 'POST':
        form_des = ItemForm(request.POST, request.FILES)

        if form_des.is_valid():
            form_des.save()
            return redirect('item_list')
    else:
        form_des = ItemForm()

        return render(request, 'upload_item.html', {'form_des': form_des})

def image_classification(request):

    form_des = ItemForm()

    if request.method == 'POST':
        if 'file' in request.FILES:
            handle_uploaded_file(request.FILES['file'], str(request.FILES['file']))

            img = np.expand_dims(cv2.resize(cv2.imread(os.path.join('./media/item/img/', str(request.FILES['file']))), (170, 100)), axis=0)
            cat_prediction = cat_classifier.predict_classes(img)[0]
            pattern_prediction = pat_classifier.predict_classes(img)[0]

            form_des.fields['title'].widget.attrs['value'] = cat_prediction
            form_des.fields['pattern'].widget.attrs['value'] = pattern_prediction
            form_des.fields['user'].widget.attrs['value'] = request.user
            form_des.fields['user'].widget.attrs['readonly'] = True

            return render(request, 'upload_item.html', {'form_des': form_des})

    else:
        return redirect('upload_item')

upload_item.html 模板

<div class="container">
  <div class="row justify-content-center">
    <div class="col-7">
      <center>
        <h2>Upload image</h2>

        <!-- <div class="row justify-content-center"> -->
            <div class="upload-btn-wrapper">
              <form action="{% url 'image_classification' %}" method="POST" enctype="multipart/form-data" data-url="image_classification/" class="my_form">
                {% csrf_token %}
                <input type="file" name="file" id="file" class="inputfile" multiple/>
                <label for="file" class="btn btn-outline-dark btn-lg mt-5 select">Choose a file</label>

                 <input class='btn btn-primary btn-lg btn-block upload_image_button' type="submit" value="Upload image" disabled/>
              </form>
            </div>
        <!-- </div> -->
        <center>
          <p class='font-weight-bold mt-5 mb-5 text-danger'>Step: 1 of 2</p>
        </center>

        <div class="separation"></div>

        <h2>Item description</h2>
      </center>
      <div class="card mb-2 mt-3">
        <div class="card-body">
          <form method="post" enctype="multipart/form-data" action="{% url 'upload_item' %}" id='item_des'>
            {% csrf_token %}
            {{form_des.title|as_crispy_field}}
            {{form_des.pattern|as_crispy_field}}
            {{form_des.color|as_crispy_field}}
            {{form_des.user|as_crispy_field}}
            <button type="submit" class='btn btn-primary btn-lg btn-block save_btn'>Save item</button>
          </form>
        </div>
      </div>
      <center>
        <p class='font-weight-bold mt-2 mb-5 text-danger'>Step: 2 of 2</p>
      </center>
    </div>
  </div>
</div>

我的问题是,当在第一个表单中单击上传图片按钮时,url 会从items/upload/description/to更改,items/upload/image_classification/并且页面会重新加载第二个表单中的自动填充部分。

我想使用 AJAX 自动填写第二个表单而不重新加载页面,但不知道该怎么做。我遵循了一些教程,但无法做到这一点。

请帮我

谢谢

[EDIT1] 根据 Adeel Siddiqui 的回答,我对views.py进行了一些更改

视图.py

def image_classification(request):

    form_des = ItemForm()
    user =str(request.user)

    if request.method == 'POST':
        if 'file' in request.FILES:
            handle_uploaded_file(request.FILES['file'], str(request.FILES['file']))

            img = np.expand_dims(cv2.resize(cv2.imread(os.path.join('./media/item/img/', str(request.FILES['file']))), (170, 100)), axis=0)
            cat_prediction = cat_classifier.predict_classes(img)[0]
            pattern_prediction = pat_classifier.predict_classes(img)[0]

            form_des.fields['title'].widget.attrs['value'] = cat_prediction
            form_des.fields['pattern'].widget.attrs['value'] = pattern_prediction
            form_des.fields['user'].widget.attrs['value'] = request.user
            form_des.fields['user'].widget.attrs['readonly'] = True

            context = {
                'tops_prediction'   :tops_prediction,
                'pattern_prediction':pattern_prediction,
                'user'            :user,
            }

            return HttpResponse(json.dumps(context))

    else:
        return redirect('upload_item')

如何从jquery 中的fillImageDescriptionText访问此上下文并在 upload_item 页面中自动填写第二个表单?

[EDIT-2]使用更新后的答案后的输出截图 在此处输入图像描述

标签: pythonjquerydjangocomputer-vision

解决方案


您可以防止在提交表单时发生默认事件。假设您的图像分类表单具有 id image-classify-form,则:

$("#image-classify-form").submit(function(event) {
    event.preventDefault();
    imageClassifyAjax();
}

您的 imageClassifyAjax 函数在哪里执行此操作(我之前忘记在第 2 行创建 FormData 对象,这导致 POST 请求失败)

function imageClassifyAjax() {
    let $form = $("#image-classify-form");
    let form_data = new FormData($form[0]);
    $.ajax({
        url: $form.attr('action'),
        type: $form.attr('method'),
        data: form_data,
        processData: false,
        contentType: false,
        dataType: 'json',
        success: function (data) {
            fillImageDescriptionText(data);
        },
        error: function (xhr) {
            console.log("Something went wrong: " + xhr.responseText);
        }
    });
}

fillImageDescriptionText 使用视图返回的 json 数据来填充图像描述的表单。所以你必须修改你的视图对 POST 方法的作用。您必须返回 HttpResponse 而不是渲染模板:

import json
from django.http import HttpResponse

def image_classification(request):

    form_des = ItemForm()

    if request.method == 'POST':
        ...
        ...
        return HttpResponse(json.dumps({'title': cat_prediction, 'pattern': pattern_prediction, 'user': request.user.email}))

fillImageDescriptionText接收这个 json 对象作为输入,所以你基本上可以:

function fillImageDescriptionText(data) {
    $("#item_des #id_title").val(data.title);
    $("#item_des #id_pattern").val(data.pattern);
    $("#item_des #id_user").val(data.user);
    $("#item_des #id_user").prop('readonly', true);
}

其中 id_ 是 django 脆皮表单或您用于表单的任何包为元素生成的 id。它主要以“id_”为前缀。您可以通过检查浏览器中的元素来检查它。


推荐阅读