今回はDjangoで作成しているWebアプリケーションにAjaxで画像をアップロードしてページに即反映できるような機能の実装の仕方をご紹介します。
クラウドストレージなどのアップロード先は既に実装済みの前提でお話いたします。
まだ画像の保存先を決めていないよ!という方はこちらの記事にクラウドストレージを提供しているCloudinaryを使った実装方法をご紹介しているので、参考にしてください😶

実装内容のデモ

今回CSSについては説明しませんが、実装内容の大体のイメージを持ってもらうためにデモをお見せします。



任意のボタンを押すとアルバムから画像が選べて、選び終わるとページにそのまま反映されるような仕組みです。

バックエンドの設定

先ずはDjangoで裏の実装をしていきます。
今回はプロジェクト内にappという名前のアプリケーションを作成して、app内で実装しています。 ※分かりやすいようにエラーが起こった時の処理などは省いています。

app/models.pyの設定

models.pyで画像をアップするデータベースを作成してください。
画像フィールドだけの簡単なものになります。

class Image(models.Model):
   image = models.ImageField(default='default/default.png')
models.pyの変更が終わったらターミナルからデータベースの作成をしてください。
$ python manage.py makemigrations
$ python manage.py migrate

app/views.pyの設定

views.pyではフロント側からPOSTで送られてきた画像データを受け取って、先ほど作成したデータベースに格納する処理を行います。
また格納した後はフロントエンドに画像のURLを返すように設定してあげます。
request.FILES['image']の部分の'image'は後のフロントエンドの実装の際に詳しく説明しますが、 フロントエンド側でデータにつけた名前を設定します。

from .models import Image
def ImageUpload(request): if request.method == 'POST': posted_img = request.FILES['image'] new_image = Image.objects.create(image=posted_img) return HttpResponse(new_image.image.url)

app/urls.pyの設定

画像のアップロード処理をするimguploadと名付けたディレクトリを作成をします。

from .views import ImageUpload
app_name = 'app'
urlpatterns = [ ...
url(r'^imgupload/$', views.ImageUpload, name='imgupload'), ... ]

これでDjango側の設定は完了です。

フロントエンドの設定

次にフロントエンド側の設定をしていきます。

htmlの設定

画像データをやりとりするinputと画像の表示先を記述してください。

<form method="post">
<input type="file" accept="image/*" id="input_image">
</form>
<div id="output">
    <img src="">
</div>


Ajaxの設定

今回はjQueryを使います。 DjangoでAjaxをする場合はトークン対策をの必要があります。
Django documentationを参照に以下のコードを記述してください。

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 = jQuery.trim(cookies[i]);
                    if (cookie.substring(0, name.length + 1) === (name + '=')) {
                        cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                        break;
                    }
        }
    }
       return cookieValue;
}

var csrftoken = getCookie('csrftoken');

function csrfSafeMethod(method) { return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method)); }

$.ajaxSetup({ beforeSend: function (xhr, settings) { if (!csrfSafeMethod(settings.type) && !this.crossDomain) { xhr.setRequestHeader("X-CSRFToken", csrftoken); } } });

次に画像が選択された時の処理をAjaxで実装していきます。
FormDataはAjaxやXMLHttpRequestの通信の際ににデータに名前をつけて送ってくれるので、
バックエンド側でこの名前のデータが欲しい!とリクエストすればすぐに取得することができます。 ここではrview.pyで記述したrequest.FILES['image']の'image'部分と同じ名前になるように設定します。 urlには先ほどapp/urls.pyで指定したディレクトリの名前をつけます。

  $("#input_image").on('change', function(){
    let file = $(this).prop('files')[0];
    let fd = new FormData();
    fd.append('image', file);
    $.ajax({
        'url': "{% url 'app:imgupload' %}", #画像アップロードの処理をするURLを指定
        'type': 'POST',
        'processData': false,
        'contentType': false,
        'data':fd
      }).done( response => {
         $("#output img").attr('src', response );
      });
  });

これで全ての実装が完成したので試しに画像をアップロードしてみてください。😚

まとめ

フロントエンドとバックエンドのデータのやりとりは結構大変ですよね。 でも慣れると結構いろんなことが可能になって楽しいので、ぜひDjangoとAjaxで色々遊んでみてください!

質問や感想などありましたらSNSからご連絡ください。
またね✋