"BOKU"のITな日常

62歳・文系システムエンジニアの”BOKU”は日々勉強を楽しんでます

ドラッグ&ドロップのjavaScript実装を作成し、django3.0画面で動作確認する/django3.0

今回はJavaScriptでドラッグ&ドロップでファイル名を取得する実装してみます。

django2.0と3.0で動作確認済です。

f:id:arakan_no_boku:20190320212948j:plain 

 

はじめに

 

今回はドラッグ&ドロップのインタフェースを実装します。

それほど難しいものでもないので、今回はJavaScriptで一から実装してみます。

実行確認の画面では前回用意したBase.htmlを使います。

arakan-pgm-ai.hatenablog.com

 

ドラッグ&ドロップ処理の実装から

 

dragdrop.jsの名称で、static/jsの下に配置します。

今回はセレクタ等にはjQueryを使って、以下のように実装しました。

 

dragdrop.js
var obj = $("#dragandrophandler");
obj.on('dragenter', function (e) 
{
    e.stopPropagation();
    e.preventDefault();
    $(this).css('border', '2px solid #0B85A1');

});
obj.on('dragover', function (e) 
{
     e.stopPropagation();
     e.preventDefault();
     $("#dragandrophandler").css('background-color', '#ffffe0');
});
obj.on('drop', function (e) 
{
     $(this).css('border', '2px dotted #0B85A1');
     e.preventDefault();
     var files = e.originalEvent.dataTransfer.files;
  
     //We need to send dropped files to Server
     $("#dropedfile").val(files[0].name);
     $("#dragandrophandler").css('background-color', '#ffffff');

});
$(document).on('dragenter', function (e) 
{
    e.stopPropagation();
    e.preventDefault();
    $("#dragandrophandler").css('background-color', '#ffffff');

});
$(document).on('dragover', function (e) 
{
  e.stopPropagation();
  e.preventDefault();
  obj.css('border', '2px dotted #0B85A1');
});
$(document).on('drop', function (e) 
{
    e.stopPropagation();
    e.preventDefault();
});

objがドロップするDivタグのエリアを指しています。

エリアにはいってきたり(dragenter)、領域内にいたり(dragover)、ドロップされたり(drop)の処理をイベントとして拾って処理をします。

objの中だけの処理しか書いていないと片手落ちなので、領域の外の動作も$(document)でドラッグ領域外のイベント処理として書いてます。

ドロップ可能領域上にいるかどうかをわかりやすくするため、領域にはいってきたら薄い黄色の背景にして、でたら白に戻すみたいにしてます。

各タグのclass定義は、すべて「bootstrap」のクラスなのですが、そのあたりのファイルをドロップするDIVタグだけはIDの値で独自制御したかったので、ドラッグ&ドロップ処理専用のCSSを書いてます。

これは、staticフォルダに「dragdrop.css」として保存しています。

 

dragdrop.css

 

#dragandrophandler
{
border:2px dotted #0B85A1;
width:500px;
height:100px;
color:#92AAB0;
text-align:left;vertical-align:middle;
padding:10px 10px 10 10px;
margin-bottom:10px;
font-size:200%;
}

 

これで準備は終わりです。 

 

簡単な画面で動作確認

 

簡単な画面を作って動作確認をやっていきます。

 

 入力画面のHTML

 

画面本体です。

前回の環境(Base.html)を使ってます。

{% extends 'base.html' %}
{% load static %}
{% bootstrap_css %}
{% bootstrap_javascript jquery='full' %}
{% load widget_tweaks %}

{% block header %}
<link rel="stylesheet" href="{% static "css/dragdrop.css" %}"></link>
{% endblock %}

{% block title %}
  サンプルその1
{% endblock %}

{% block content %}
<div class="container">
    <form action="" method="post">{% csrf_token %}
        {% if textone %}
        <h4>ドロップされたファイル名</h4>
        <div class="form-group row my-4">
            <label class="col-lg-2 col-form-label"><h2>{{cnamelabel}}</h2></label>
    		<div class="col-lg-8">       
            	<h2>{{ cname }}</h2>
            </div>	
        </div>
        <a href="{% url 'dragdrop' %}"><h2>もう一回</h2></a>
        {% else %}
        <h4>ドラッグエリア</h4>
            <div class="form-group row my-4">  
        	<div id="dragandrophandler" class="border col-lg-9">ここにファイルをドロップ</div>
        </div>
        <div class="form-group row my-4">         
            <label class="col-lg-2 col-form-label"><h4>{{form.textone.label}}</h4></label>
    		<div class="col-lg-8">       
	            {{form.textone|add_class:"form-control bg-warning"}}
    		</div>
        </div>
        <div class="form-group row my-4">         
    		<div class="col-lg-2">       
	            <button type="submit" class="btn btn-primary">サブミット</button>
    		</div>
    		<div class="col-lg-8"></div>       
        </div>    
        {% endif %} 
    </form>
</div>  
<script type="text/javascript" src="{% static "js/dragdrop.js" %}"></script>  
{% endblock %}

補足します。

<header>部でdragdrop.cssを、後半の<script></script>タグで「dragdrop.js」を読み込んでいます。 

{% block content %}の中身、すなわちbody部については、初期表示画面とsubmitボタンを押した後に表示する画面を両方書いてます。

 {% if textone %}から{% else %}までが、Submit後の結果表示画面。

Submitで呼ばれるメソッドの中で「textone」変数をセットするので、初期表示の時はtextoneは空になります。

だから、{% else %}より後ろが初期表示されるわけです。

  

Pythonのソースの修正

 

さて、HTML側の準備できたので、pythonのソースを書いていきます。

 

forms.py

 

上記HTMLの以下の部分がテキスト入力フィールドになります。

{{form.textone|add_class:"form-control bg-warning"}}

 form.textone等の部分が、djangoの組み込みフォームで、add_class以降で、その入力フォームにbootstrapのCSSを適用しています。

このフォームの定義は、forms.pyで行います。

from django import forms


class UserForm(forms.Form):
    textone = forms.CharField(
        label='ファイル',
        widget=forms.TextInput(
            attrs={
                'id': 'dropedfile'}))

CharFieldがテキスト入力フィールドになります。 

JavaScriptでテキストボックスに値をセットするために、IDセレクタを使ってます。

${"#dropedfile")の部分です。

これを有効にするために、idをセットしています。

 

views.py

 

このフォームを使うメソッドはviews.pyに書きます。

from django.shortcuts import render
from . import forms
from django.template.context_processors import csrf


def dropdemo(request):
    if request.method == 'POST':
        c = {
            'textone': request.POST["textone"],
            'cnamelabel': '→→→',
            'cname': request.POST["textone"] + 'です。'
        }
    else:
        form = forms.UserForm(label_suffix=':')
        c = {'form': form}
        c.update(csrf(request))
    return render(request, 'dragdrop.html', c)

そして、あとは呼び出すURLです。

 

urls.py

 

urls.pyに追記します。

path('demo01/', views.dropdemo, name='dragdrop'),

{ルートURL}/demo01/ で画面を呼び出し、views.pyのdropdemoメソッド、HTMLは「dragdrop.html」を使って表示する・・という意味です。

 

実行してみます

 

これで動くはずです。

プロジェクトフォルダをカレントにして「python  manage.py runserver」ですね。

それで、「http://localhost:8000/demo01/」です。

f:id:arakan_no_boku:20191214230239p:plain



 適当な画像ファイルをドロップして、「サブミット」ボタンを押すと。

f:id:arakan_no_boku:20191214230336p:plain

ちゃんと、ドロップしたファイル名が引き継がれてます。

今回は、とりあえずドラッグ&ドロップしてファイルオブジェくトからファイル名を取得だけしてみました。

ドロップしたファイルオブジェクトを使って何かする・・のは、別の機会に。

ではでは。