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

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

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

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

Python

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

Q&A

解決済

1回答

224閲覧

djangoでformで入力されたデータを保存し、次のページで表示したい

gogatu

総合スコア7

Django

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

Python

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

0グッド

0クリップ

投稿2024/07/20 03:11

編集2024/07/20 09:06

実現したいこと

djangoでformで入力されたデータを保存し、次のページで表示したい。
modelは2種類あり、1種類はフォームから入力、もう1種類は入力されたデータを基に計算して算出した値を代入したい。
現在のソースコードではフォームから入力し、それを表示するだけになっている。

home.htmlでフォームを入力させ、routesearch.htmlで入力内容を表示させたい。

発生している問題・分からないこと

次のページに行っても入力された内容が表示されない。
入力内容を変数などに取り出す方法がわからない。

該当のソースコード

models.py

1from django.db import models 2 3class Spot(models.Model): 4 purpose = models.CharField(max_length=128) 5 route = models.CharField(max_length=128, blank=True) 6 7 def __str__(self): 8 return self.purpose 9

forms.py

1from django import forms 2from my_app.models import Spot 3 4class PurposeForm(forms.ModelForm): 5 class Meta(): 6 model = Spot 7 fields = ('purpose',) 8 exclude= ('route',)

views.py

1from django.shortcuts import get_object_or_404, redirect, render 2 3from my_app.models import Spot 4from . import forms 5 6from myproject.routesearch.routesearch import routesearch 7 8 9def create_route(request): 10 #モデルのインスタンス作成 11 spot = Spot() 12 13 if request.method == "POST": 14 form = forms.PurposeForm(request.POST, instance=spot) 15 16 #フォームが正常であれば 17 if form.is_valid(): 18 form.save() 19 20 spot = form.save(commit=False) 21 spot.save() 22 return redirect('my_app/routesearch.html') 23 24 else: 25 form = forms.PurposeForm(instance=spot) 26 return render(request, "my_app/home.html", {'form': form}) 27 28 29def display_route(request): 30 data = Spot.objects.all() 31 return render(request, 'my_app/routesearch.html', {'data': data}) 32

home.htmls

1<!DOCTYPE html> 2<html lang="ja"> 3<html> 4 <head> 5 <meta charset="utf-8" /> 6 <title>My App</title> 7 </head> 8 9 <body> 10 <h1>My App</h1> 11 <p> 12 Input purpose 13 </p> 14 <form 15 action="{% url 'my_app:routesearch' %}" 16 method="post" 17 > 18 {{ form.as_p }} 19 {% csrf_token %} 20 <button type="submit">RouteSearch</button> 21 </form> 22 </body> 23</html>

routesearch.html

1<!DOCTYPE html> 2<html lang="ja"> 3<html> 4 <head> 5 <meta charset="utf-8" /> 6 <title>M App</title> 7 </head> 8 9 <body> 10 {% for spot in spot %} 11 <tr> 12 <th>{{ data.purpose }} 13 <th>{{ data.route }} 14 </tr> 15 {% endfor %} 16 </body> 17</html>

試したこと・調べたこと

  • teratailやGoogle等で検索した
  • ソースコードを自分なりに変更した
  • 知人に聞いた
  • その他
上記の詳細・結果

様々な実装例を確認して変更を施した。
request.methodの判定をしているif文の中身をどのようにすればよいのか調べ、create_route関数内を成功している事例に近づけたが、結果は変わらなかった。
いろいろ試してみた結果、フォームは正しく機能しているが、そのフォームの中身がデータベースに反映されていないことが原因だと考えられる。

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

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

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

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

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

yametai

2024/07/21 11:08

再現確認をしていて気付いた点がありました。 home.htmlsからsubmitするとviews.pyのcreate_route関数が呼び出される想定だと思います。 `if request.method == "POST":`の中にprintを記述したらそこが動いていますでしょうか? urls.pyが質問欄に記載されていないためわからないですが、home.htmlsの15行目でroutesearchと記述されているため別のところにpostされているのではないかと思いました。
gogatu

2024/07/22 09:58

printをしてみましたが、`if request.method == "POST":`の中身が実行されていませんでした。この部分に問題がありそうです。現在原因を探しています。
yametai

2024/07/22 11:08

コメントありがとうございます。 テンプレートファイル(home.htmls)に記述するurlと urls.pyファイルに記述する内容の対応を見直すと良いかもしれませんね。 チュートリアルの次のリンクを読むと理解が深まるかなと思います。 もっとビューを書いてみる [はじめての Django アプリ作成、その 3 | Django ドキュメント | Django](https://docs.djangoproject.com/ja/5.0/intro/tutorial03/#writing-more-views) テンプレート内のハードコードされたURLを削除 [はじめての Django アプリ作成、その 3 | Django ドキュメント | Django](https://docs.djangoproject.com/ja/5.0/intro/tutorial03/#removing-hardcoded-urls-in-templates)
gogatu

2024/07/22 13:02 編集

コメントありがとうございます。 教えていただいたurlを見て、理解が深められるようにします。 ソースコードについてですが、もう一度最初から作り直すことにしまして、そちらでひとまずデータベース2種類ともに手入力させることには成功しました。 views.pyのソースコードの一部はこちらです。 def create_route(request): >>>post = Spot() >>># ページロード時 >>>if request.method == 'GET': >>>>>>form = PurposeForm(instance=post) >>>>>>return render(request, 'my_app/spot_form.html', {'form': form}) >>># 実行ボタン押下時 >>>if request.method == 'POST': >>>>>>form = PurposeForm(request.POST, instance=post) >>>>>>if form.is_valid(): >>>>>>>>>post = form.save(commit=False) >>>>>>>>>post.save() >>>>>>return redirect('my_app:read_route') このソースコードを質問として出したソースコードを比較すると、違うところはフォームのバリテーションが問題なかった時、最初にform.save()をしていなかったことくらいでしょうか。私にはいまいち原因がわかりません...。もう少し原因を考えてみようと思います。 長い間ソースコードについていろいろ考えて調べて下さり、本当にありがとうございました。感謝しております。
guest

回答1

0

ベストアンサー

そのフォームの中身がデータベースに反映されていないことが原因だと考えられる。

仕様がわからないので見当違いなことを書いてしまうかもしれません・・

py

1>>> from myapp.models import Article 2>>> from myapp.forms import ArticleForm 3 4# Create a form instance from POST data. 5>>> f = ArticleForm(request.POST) 6 7# Save a new Article object from the form's data. 8>>> new_article = f.save() 9 10# Create a form to edit an existing Article, but use 11# POST data to populate the form. 12>>> a = Article.objects.get(pk=1) 13>>> f = ArticleForm(request.POST, instance=a) 14>>> f.save()

モデルからフォームを作成する | Django ドキュメント | Django

上に引用したドキュメントによりますと、
新たにデータベースオブジェクトを生成して保存する場合は
次のようになるみたいです。

py

1f = ArticleForm(request.POST) 2new_article = f.save()

views.pyの14行目で保存されていないインスタンスを使用してしまっているのが悪影響しているのかもしれないと思いました。
24行目のelseの方でもspotインスタンスが使われていて、そのあたりがどういう仕様になっているのか理解できませんでした・・
見当違いでしたらごめんなさい・・

追記です。

コメントありがとうございます。

仕様としては、method == "POST"の時にフォームの内容をモデルに保存し、そうでないときはreturn renderで同じページを表示させるという風に考えております。

新規登録の際に、最初に空っぽのフォームを表示する処理(else)と、フォームを入力して送信した時に保存する処理(if true)ということですかね。

py

1# if a GET (or any other method) we'll create a blank form 2 else: 3 form = NameForm()

フォームを使う | Django ドキュメント | Django

最初に空っぽのフォームを表示するのは上の引用にある通りのようです。
データベースオブジェクトを生成するのは本当に必要になったとき(if true)だけにした方が良いかなと思いました。
フレームワークが色々やってくれるのは便利ですが、基本通りにやらないと何が影響して問題になっているのかわからなくなってしまいそうですので、最初はシンプルにドキュメント通りにやってみるのが良いかなと思います。

追記2です。

コメントありがとうございます。

modelの中身のうち、片方のみを入力させるようなフォームにしてもう片方は入力された結果から計算して求めるという形をとりたい

purposeはユーザーが入力、routeはプログラムによって計算されたものということですね。
コメントのコードを元に少し修正してみました。
コード内のコメントのリンク先も参照してみてください。

py

1def create_route(request): 2 if request.method == "POST": 3 form = forms.PurposeForm(request.POST) 4 if form.is_valid(): 5 # spotのインスタンスが無駄に生成されてしまっていましたのでリンク先を参考に修正してみました。 6 # [モデルからフォームを作成する | Django ドキュメント | Django](https://docs.djangoproject.com/ja/5.0/topics/forms/modelforms/#the-save-method) 7 # save() メソッド 8 spot = form.save(commit=False) 9 spot.created_route = "created_route" 10 spot.save() 11 # リダイレクトにテンプレートを記述しているっぽい?ところが気になりました。リンク先も参照してみてください。 12 # [フォームを使う | Django ドキュメント | Django](https://docs.djangoproject.com/ja/5.0/topics/forms/#the-view) 13 # [Django のショートカット関数 | Django ドキュメント | Django](https://docs.djangoproject.com/ja/5.0/topics/http/shortcuts/#redirect) 14 return redirect('my_app/display.html') 15 else: 16 form = forms.PurposeForm() 17 return render(request, "my_app/home.html", {'form': form})

うまく保存されていないようです。

これはどのように確認されていますでしょうか?
Djangoのデータベースを操作する部分はPythonの対話シェルから確認することができます。
続きの部分はリンク先を参照してSpotが取得できるか確認してみると良いかなと思います。
(Webから表示確認する部分は一旦切り離して、一つずつ問題を解決していく方がスムーズかなと思います。)

API で遊んでみる

さぁ、 Python 対話シェルを起動して、 Django が提供する API で遊んでみましょう。 Python シェルを起動するには、以下のコマンドを実行します:

sh

1python manage.py shell

はじめての Django アプリ作成、その 2 | Django ドキュメント | Django

投稿2024/07/20 15:00

編集2024/07/21 03:17
yametai

総合スコア255

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

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

gogatu

2024/07/21 00:48 編集

ご回答いただき、ありがとうございます。 いただいた回答をもとに変更を加えてみましたが、うまくいきませんでした。 djangoは始めたばかりでまだ理解が浅いため、うまく説明ができずに申し訳ありません。 仕様としては、method == "POST"の時にフォームの内容をモデルに保存し、そうでないときはreturn renderで同じページを表示させるという風に考えております。 教えていただいた新しい変数に保存する方法についてですが、20行目にて教えてくださったドキュメントと同じような保存方法を行っておりますので、そこで条件を満たしているのではないかな、と初心者なりに考えております。もし仕様などを見ていただき、変更を加えるべき点が見つかりましたら、ご連絡いただけると幸いです。
gogatu

2024/07/21 02:39 編集

データベースオブジェクトの作成位置を調整したり、その他変更を施してみましたが、うまく保存されていないようです。現状こうなっております。 ```views.py def create_route(request): |---if request.method == "POST": |---|---spot = Spot() |---|---form = forms.PurposeForm(request.POST, instance=spot) | | |---|---if form.is_valid(): |---|---|---input_purpore = form.save(commit=False) |---|---|---created_route = "created_route" | | | |---|---|---spot = Spot(purpote=input_purpore, route=created_route) | | |---|-------spot.save() |---|---return redirect('my_app/display.html') | |---else: |---|---form = forms.PurposeForm() |---|---return render(request, "my_app/home.html", {'form': form}) ``` modelの中身のうち、片方のみを入力させるようなフォームにしてもう片方は入力された結果から計算して求めるという形をとりたいと考えています。それが悪影響を及ぼしているのでしょうか。
gogatu

2024/07/21 04:58

追記ありがとうございます。 spot = form.save(commit=False) spot.created_route = "created_route" spot.save() こちらの部分のspot変数は、spot=Spot()で作成したモデルのインスタンスで間違いないでしょうか。 データベースのチェックはadmin/で確認しております。 動作後、admin/で確認してもデータベースのデータ数が増えていないため、保存できていないと考えています。
yametai

2024/07/21 07:13 編集

コメントありがとうございます。 回答者が回答のコメントをしても通知が届かないと思いますが、直接的な回答ではないのでコメントに書きますね。 > こちらの部分のspot変数は、spot=Spot()で作成したモデルのインスタンスで間違いないでしょうか。 これは間違いですね。 > ModelForm のサブクラスはキーワード引数 instance として既存のモデルインスタンスを受け取ることができます; > 指定されない場合は、save() は指定されたモデルの新しいインスタンスを生成します: > [モデルからフォームを作成する | Django ドキュメント | Django](https://docs.djangoproject.com/ja/5.0/topics/forms/modelforms/#the-save-method) saveメソッドが新しいSpotのインスタンスを生成してくれるはずです。 自分で独自にSpotのインスタンスを生成する必要はないはずです。 リンク先のドキュメントもよく読んでみてください。 > データベースのチェックはadmin/で確認しております。 そうなのですね。じゃあやっぱり登録されていないのですね。 --- ここから追記です。 使うフィールドを選択する [モデルからフォームを作成する | Django ドキュメント | Django](https://docs.djangoproject.com/ja/5.0/topics/forms/modelforms/#selecting-the-fields-to-use) ごめんなさい。。 訂正です。 独自でモデルのインスタンスを生成しておいてフォームに渡すことでも大丈夫みたいですね。 excludeのフィールドがある場合の例がリンク先に記載されていました。(リンク先の「注釈」の部分です) 使うフィールドを`fields = ('purpose',)`のようにタプル?で記述しているようですが、 リンク先は`exclude = ["title"]`のようにリストです。 詳しくないですが、このあたりが違っていても問題ないのでしょうか? モデルに問題があるのか、フォームに問題があるのか、切り分けのために、 フォームを経由せずにモデルだけを使って保存の処理をしてみたらちゃんと保存されるか確認してみると良いかもしれません。 ちゃんと保存されるようでしたらフォームに問題があると思いますので、フォームの方を調べれば良いことになると思いました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.40%

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

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

質問する

関連した質問