くらげになりたい。

くらげのようにふわふわ生きたい日曜プログラマなブログ。趣味の備忘録です。

Django x jQuery x Ajaxで非同期にファイルをアップロードしてサーバ側で処理をする

前に記事で書いた処理のファイルバージョン。

wannabe-jellyfish.hatenablog.com

見た目的にはこんな感じ。

f:id:wannabe-jellyfish:20170625085507p:plain

HTML側

<!-- フォーム部分 -->
<form id="form" class="form" action="upload_file" method="post" enctype="multipart/form-data">
  {% csrf_token %}
  <div class="input-group">
    <input type="text" class="form-control" readonly="">
    <label class="input-group-btn">
      <span class="btn btn-success">
          Choose File<input type="file" name="file" style="display:none">
      </span>
    </label>
  </div>
</form>

<!-- Ajaxで返ってきた結果を挿入する部分 -->
<div id="result-table" class="row result-table"></div>

<!-- 読み込み中のローディング画像 -->
<div id="loading-div" class="row" style="display:none">
  <img src="{% static 'svg/loading.svg' %}" class="center-block">
</div>

ローディング画像はLOADING.IOで作成
ファイルのフォームは、ynkさんのQiitaを参考に良い感じに。

javascript

//formのinput[type="file"]が変更時の処理
$(document).on('change', ':file', function() {
  // input[type="file"]のファイル名をinput[type="text"]に表示する処理
  var input = $(this);
  numFiles = input.get(0).files ? input.get(0).files.length : 1;
  label = input.val().replace(/\\/g, '/').replace(/.*\//, '');
  input.parent().parent().prev(':text').val(label);

  //Ajaxはここから
  $.ajax({
      url: $("#form").attr("action"),
      type: 'POST',
      data: new FormData($("#form").get(0)),
      processData: false,
      contentType: false,
      beforeSend: function(xhr, settings) {
         //リクエスト送信前の処理
         // CSRFTokenを設定したり、前の結果を削除したり、ローディングを表示したり
         xhr.setRequestHeader("X-CSRFToken", $("input[name='csrfmiddlewaretoken']").val());
         $('#result-table').empty();
         $("#loading-div").show();
      },
  }).done(function(data, textStatus, jqXHR){
      // 成功したら、結果を追加する
      $tbody.append($(data));
  }).fail(function(jqXHR, textStatus, errorThrown){
      // 失敗したら、コンソールにログを吐く
      console.log(jqXHR + "\n" + textStatus + "\n" + errorThrown);
  }).always(function(data, textStatus, jqXHR){
      // 成功しても、失敗しても、レスポンスが返ってきたら、ローディングを非表示にする
      $("#loading-div").hide();
  });
});

ここの記事曰く、

ここでポイントになるのが、
processData と contentType を false にすることです。

processData は data に指定した値を文字列に変換するかどうか設定する項目です。
初期値は true となっており、このままですとURLエンコードされた値が送信されます。
ファイルの送信時は変換不要ですから、false にしておきます。

Django/Python

@require_POST
def upload_file(request):
    try:
        req_file = request.FILES['file']
        # お好みの処理をして、
        params = {
          # お好みのパラメタを用意して、
        }
        # お好みのテンプレートを使って、HTMLをレスポンスとして返す
        response = render(request, 'ajax_result.html', params);
        return HttpResponse(response)
    except:
        # 例外が発生したら、404を返す
        traceback.format_exc()
        return Http404("message")

以上!!

参考になる書籍

基礎から学ぶ Django

基礎から学ぶ Django

  • 作者: 関根裕紀,新井正貴
  • 出版社/メーカー: シーアンドアール研究所
  • 発売日: 2019/07/01
  • メディア: 単行本(ソフトカバー)
  • この商品を含むブログを見る

Python Django 超入門

Python Django 超入門

現場で使える Django の教科書《基礎編》

現場で使える Django の教科書《基礎編》

参考にしたサイト様