質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Django

DjangoはPythonで書かれた、オープンソースウェブアプリケーションのフレームワークです。複雑なデータベースを扱うウェブサイトを開発する際に必要な労力を減らす為にデザインされました。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

1回答

5853閲覧

プログラム処理中にローディング画面を表示する方法

study_111

総合スコア82

Django

DjangoはPythonで書かれた、オープンソースウェブアプリケーションのフレームワークです。複雑なデータベースを扱うウェブサイトを開発する際に必要な労力を減らす為にデザインされました。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

0クリップ

投稿2020/06/28 08:27

編集2020/07/01 05:39

Djangoでアプリ開発を行っているのですが、フォームなどからボタンを押した時に、プログラムの処理が行われ、次の画面に遷移する流れの中で、プログラムの処理が行われている間にローディング画面を表示したいと考えています。
こちらは、javascriptやCSSで作成されるものだと思うのですが、プログラムを読み込んでいる間のみローディング画面を表示するというのはどのようにすれば良いかが分かりません。
どなたかご助言頂けましたら幸いです

追記

以下は、index.htmlです

{% load static %} <!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="ie=edge"/> <link rel="stylesheet" type="text/css" href="{% static 'polls/css/style.css' %}"> <title>demo</title> </head> <body> <div class="loader hidden" id="loading">Loading...</div> <form id="form" action="{% url 'polls:check' %}" method="post"> {% csrf_token %} <input type="url" name="check_url" placeholder="http://example.com"/> <button type="button" onclick="sendData()">送信</button> </form> <script src="{% static 'polls/js/app.js' %}"></script> </body> </html>

以下は、views.pyです

def check(request): input_url = request.POST['check_url'] test_data = {'test':'sssss','test2':'aaaaaaa'} print('ok') return render(request,'polls/check.html',{'test_data': test_data})

以下はcheck.htmlです

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> </head> <body> <p>check.htmlです</p> </body> </html>

以下は、app.jsです

function showElement(e) { e.classList.remove("hidden"); } function hideElement(e) { e.classList.add("hidden"); } async function sendData() { // ローディング画面を表示する showElement(document.getElementById("loading")); //formデータを取得 let formElem = document.getElementById("form") console.log(formElem) let formUrl = formElem.action; let formData = new FormData(formElem); // console.log(formData) let response = await fetch(formUrl, { method: 'POST', body: formData }); // ローディング画面を隠します hideElement(document.getElementById("loading")); if(response.ok){ //成功の場合の処理 // console.log(response) document.open(); document.write(await response.text()); document.close(); // 前のページへ正しく戻れるようページ歴史に追加する history.pushState(null, "", "/polls/check"); }else{ //失敗の場合の処理 } }

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

そうしたいと、フォームボタンのデフォルトを使えません。JavaScriptでフォームデータを送信しないといけないです。

button元素はデフォルトではフォームデータを送信しますが、ここではそうしたくないため、type="button"をつけます。

html

1<form id="form"> 2 <!-- フォーム --> 3 <button type="button" onclick="sendData()">送信</button> 4</form>

js

1async function sendData() { 2 3 // ローディング画面を表示する 4 5 // 送信先とフォームデータを取得する 6 let formElem = document.getElementById("form"); 7 let formUrl = formElem.action; 8 let formData = new FormData(formElem); 9 // フォームデータを送信する 10 let response = await fetch(formUrl, { 11 method: 'POST', 12 body: formData 13 }); 14 15 // ローディング画面を隠します 16 17 // 送信成功したかを検査 18 if (response.ok) { 19 // 成功の場合の処理 20 // fetchで取得するページで今のページを書き換える 21 document.open(); 22 document.write(await response.text()); 23 document.close(); 24 // 前のページへ正しく戻れるようページ歴史に追加する 25 history.pushState(null, "", "polls/check"); 26 } else { 27 // 失敗の場合の処理 28 } 29 30}

DemoコードをJSFiddleでご覧ください。

追記

コメントと合わせて、DjangoでHeaderのRefererを読んで動作を分ける例を作ります。

python

1def check(request): 2 referer = request.META.get('HTTP_REFERER', '') 3 # KeyError の場合 get は2つ目の引数の値を返す 4 if !referer.endswith('check'): 5 form_data = request.POST 6 return render(request, 'polls/check_loading.html', form_data} 7 8 input_url = request.POST['check_url'] 9 test_data = {'test':'sssss','test2':'aaaaaaa'} 10 print('ok') 11 return render(request,'polls/check.html',{'test_data': test_data})

投稿2020/06/28 10:56

編集2020/07/01 06:22
YufanLou

総合スコア463

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

study_111

2020/06/28 12:15 編集

ご回答ありがとうございます。 ご提示頂いたコードの構文を調べておりましたら、「async」という非同期構文の理解が必要だということが分かったのですが、javascriptの理解も曖昧だった為、きちんとjavascriptの非同期処理に関して学習し直してから、ご提示頂きましたコードを参考に、実装を試してみたいと思います。
study_111

2020/06/29 11:21

ご丁寧に追記頂きまして、ありがとうございます。 sendData関数により、リクエストを送信することは理解出来たのですが、Django側のurls.pyはformの「name」によってコントローラー側のどのメソッドで処理を送るか振り分けているかと思いますが、formのnameの設定やdjangoの「action="{% url 'polles:test' %}" 」こういった表記から値を取得することは出来ませんでしょうか?
YufanLou

2020/06/30 13:23

その表記はformの請求先を指定していますが、デフォルトの場合だけ、ブラウザーが送信するときに参照します。ここではJavaScriptで送信するので、その請求先をJavaScriptに取得しておいたら大丈夫です。追記します。
study_111

2020/07/01 02:50 編集

ご追記頂きまして、ありがとうございます。 ご丁寧に教えて下さりましたおかげでプログラム側で処理を渡すよう実装出来ました。 重ね重ね申し訳ないのですが、実の所、後一点のみ問題がございます。 formのaction先が「http://127.0.0.1:8000/polls/check」だった場合であってもコントローラー側でプログラム処理を終えた際には、元のページ(http://127.0.0.1:8000/polls/)が表示されてしまいます。その為、「http://127.0.0.1:8000/polls/check」こちらのページを表示させるようにしたいと考えているのですが、実現する手段はございますでしょうか。 大変お手数をおかけして申し訳ないのですが、ご教示頂けましたら幸いです。 よろしくお願い致します。
YufanLou

2020/07/01 02:49

成功の場合、別のページを表示したいのですね。”成功の場合の処理”のところで window.location.assign("http://127.0.0.1:8000/polls/check") をすれば大丈夫です。
YufanLou

2020/07/01 02:55

すみません、そうしたらもう一つの請求を送信するかつ前のレスポンスを捨てますので、多分ご要望と違います。もうちょっと調べてきます。
study_111

2020/07/01 02:57

お手数をおかけし、申し訳ございません。 自分も実現する方法がないか調べてみます。
YufanLou

2020/07/01 03:18

追記しました。JSFiddleも更新しました。ご覧ください。お役に立てて嬉しいです。
study_111

2020/07/01 04:01 編集

追記頂きまして、ありがとうございます。 追記頂きました内容で実装しましたら、formが送信され、プログラム処理が終了した後、「http://127.0.0.1:8000/security_tool/check」こちらのページが表示されました。 コントローラー側で、「return render(request,'security_tool/check.html')」こちらを記述していた為、「check.html」の内容も表示されることが確認出来ました。 ただ、何度もご追記頂いている中申し訳ないのですが、「http://127.0.0.1:8000/security_tool/check」こちらのページが表示された後に、リロードを行いましたら、「MultiValueDictKeyError at /polls/check 'check_url'」とのエラーが出力されてしまいました。「check_url」はコントローラー側(input_url = request.POST['check_url']の形)で受け取っているformのnameの値になります。 また、戻るボタンより前のページに戻った場合も同様のエラーメッセージが表示されてしまっている状況でございます。何度も申し訳ないのですが、お手すきの際にでもチェックの程、頂けましたら幸いです。
YufanLou

2020/07/01 04:11

エラーに関して説明します。fetchを使えてPOST請求を送信しますが、リロードしたらGET請求を送信してしまい、フォームデータも送信してなくなります。ですから、request.POST['check_url']がPOSTに'check_url'というKeyを見つけなくなって、KeyErrorをraiseします。 ブラウザーがフォームを送信したら、リロードする際「フォームデータを再送しますか?」みたいなプロンプトがありますが、JavaScriptが送信したからそのプロンプトがないです。 戻るボタンにもエラーが出るとは思いませんでしたけど。 リロードの場合はどんな動作をしたいですか?historyの行を削除したらどうですか?
study_111

2020/07/01 04:51

ご丁寧にご説明下さり、ありがとうございます。 何度もすみません。 リロードした場合についてなのですが、元のフォーム画面を表示せず、check.htmlの内容が表示されるだけの形にしたいと考えております。 その為、実質的には、javascriptからfetchにてリクエストを送り、プログラム側で処理を行なった後は、そのまま、元のページにはレスポンスを返さず、「http://127.0.0.1:8000/security_tool/check」こちらのページを表示するだけの形にしたいと考えております。 もし、こちらの実現が難しい場合、一度レスポンスが戻ってきた後、GETで「http://127.0.0.1:8000/security_tool/check」へレスポンスで返ってきた値と一緒に送信するといったこと手もあるかなと思ったのですが、あまり現実的な手段ではありませんでしょうか?
YufanLou

2020/07/01 05:09

確認しておきたいが、例の実現の流れはこうなのはずです: 1. フォームの送信ボタンを押す 2. ローディング画面をフォームのURLの下に表示する 3. check.htmlをcheckのURLの下に表示する 4. checkのURLの下でリロードするとエラー 違うところがありましたら教えてください。 リロードについて、checkのページで必ずフォームデータが必要ですか?そうではないと、フォームデータがないバーションを作ればどうでしょうか? フォームデータが必要だとしたら、ブラウザーのIndexDBにフォームデータを保存するか、サーバーでそのユーザーのセッションに保存するかの二択があります。 どうして戻りボタンでもエラーがまだわかりませんが、調べていきます。
study_111

2020/07/01 05:24 編集

自分がきちんと説明をしていなかったばかりに、確認させてしまう形となりすみません。 ご確認頂きました流れで間違いございません。 > リロードについて、checkのページで必ずフォームデータが必要ですか? こちらですが、フォームのデータはcheckのページでは必要ないですが、プログラムの処理が終わった時にに、いくつかの変数をcheck.htmlへ持たせたいと考えております。
study_111

2020/07/01 05:24 編集

今更で申し訳ないのですが、自分で作成しましたコードを質問本文に追記したいと思います。
study_111

2020/07/01 05:38

コードの方、追記致しました。 お手数ですが、ご確認頂けましたら幸いです。
YufanLou

2020/07/01 06:01

コード助かります。フォームデータがないと check.html の内容が意味なくなってしまいましたら、必要だと思います。そうだとしたら一番簡単な作り方はローディング画面の位置を変えると思います。History APIが僕もまだなれていませんので。考えはこちら: 1. 隠しフォームとローディング画面で check_loading.html を作ります 2. index.html のフォームの送信ボタンをデフォルトに戻し、押すとブラウザーが /check に送信します 2. /check で受信したデータをそのまま check_loading.html の隠しフォームに入れて、ローディング画面と一緒にブラウザーに返して表示します 3. check_loading.html でJavaScriptでフォームデータをもう一回送信します 4. /check で受信したデータを本気な処理に渡して、本当の結果 check.html をJavaScriptに返します 5. check_loading.html で本当の内容を書き換えます こうすれば、/check をリロードするたびフォームデータを自動的に再送します。欠点はindexでの送信が二回送信となりまして、初回ロードはネットワーク遅延の影響が二倍となります。 2が4と分けるにはRefererというHeaderを読みまして、/check そのページと一致しないとローディング画面を返して、一致したら処理結果を返します。
study_111

2020/07/01 13:03 編集

すみません。自分自身勘違いしてしまっていた部分がございました。具体的には、こちらのサイトのように作成したいと考えております。 処理の流れは以下の手順で実装を行いたいです。 1.URLを入力する 2.ローディング画面を表示する 3.結果のページが表示される また、3番の結果のページなのですが、リロードした場合は再度postを再送する形にしたいです。 何度も誠に申し訳ないです。
YufanLou

2020/07/01 10:33

そのサイト実はSPAです。Single Page Applicationで、ページは一つだけで、全ての内容のテンプレートがその1ページにあります。MustacheというJSテンプレートエンジンを使っています。画面の変化はJavaScriptでAPIに請求しJsonデータを取得しテンプレートに入れます。URLもHistory APIで書き換えています。そうしたいなら、今までと結構違います。
study_111

2020/07/01 11:08

javascriptのテンプレートエンジンを使用しているのですね。 一度、Mustacheについて調べてみたいと思います。 ともあれ、HistroyAPIの理解は必須ということがわかりました為、こちらについても調査してみたいと思います。
study_111

2020/07/01 11:44

YufanLouさんのおかげでローディング画面の実装は完了しました為、一度こちらの質問はクローズとさせて頂きたいと思います。 ご丁寧に教えて下さり、誠にありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問