今回は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からご連絡ください。
またね✋