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

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

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

FlaskはPython用のマイクロフレームワークであり、Werkzeug・Jinja 2・good intentionsをベースにしています。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

SQLAlchemy

SQLAlchemyとはPython 用のORMライブラリです。MIT Licenceのオープンソースとして提供されています。

Q&A

解決済

2回答

1126閲覧

Flaskを用いて別ページに変数を送りたいのですがうまくいきません

jyansinkai

総合スコア66

Flask

FlaskはPython用のマイクロフレームワークであり、Werkzeug・Jinja 2・good intentionsをベースにしています。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

SQLAlchemy

SQLAlchemyとはPython 用のORMライブラリです。MIT Licenceのオープンソースとして提供されています。

0グッド

0クリップ

投稿2021/08/30 01:22

いつもお世話になっております。

https://tech-diary.net/flask-introduction/
上記ページを参考に、FlaskとSQLAlchemyを用いて、[todo.db]の[Post]というテーブルの内容を別ページに送ろうとしております。

Python

1from flask import Flask, render_template, request, redirect 2from datetime import datetime 3from flask_sqlalchemy import SQLAlchemy 4 5app = Flask(__name__) 6app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///todo.db' 7db = SQLAlchemy(app) 8 9class Post(db.Model): 10 id = db.Column(db.Integer, primary_key=True) 11 title = db.Column(db.String(30), nullable=False) 12 detail = db.Column(db.String(100)) 13 due = db.Column(db.String(20)) 14 15 16@app.route('/', methods=['GET', 'POST']) 17def index(): 18 if request.method == 'GET': 19 #↓↓↓ここでデータベースのデータを取り出し、postsという名前をつけてindex.htmlへ送っていると思っている 20 posts = Post.query.all() 21 return render_template('index.html', posts=posts) 22 #↑↑↑ 23 else: 24 title = request.form.get('title') 25 detail = request.form.get('detail') 26 due = request.form.get('due') 27 new_post = Post(title=title, detail=detail, due=due) 28 29 db.session.add(new_post) 30 db.session.commit() 31 return redirect('/') 32 33@app.route('/create') 34def create(): 35 return render_template('create.html') 36 37if __name__ == "__main__": 38 app.run(debug=True)

データを受け取って表示させたいindex.htmlは以下の通りです。

HTML

1{% extends 'base.html' %} 2{% block body %} 3<h1>トップページ</h1> 4{% for post in posts %} 5 <h2>タイトル : {{ post.title }}</h2> 6 <h2>詳細 : {{ post.detail }}</h2> 7 <h2>期限 : {{ post.due }}</h2> 8{% endfor %} 9{% endblock %}

また、データベースは、テーブル名Postで、以下の4つの列が入っています。
id title detail due
データが入っていることは、DB Brouser for SQLite で確認しました。(idは全てNULLです)

以上の状況で、コマンドプロンプトから当該プログラムのある部分へ行き実行させ、ブラウザでhttp://localhost:5000/へアクセスした画面がこちらになります。

肝心のデータが表示されていません

各項目の右にデータが表示されるだろうと考えましたが、これが表示されません。
create.htmlで書き込んだデータは正しくデータベースに入りましたので、表示のさせ方がおかしいのかと考えておりますが、どうにも分かりませんでした。修正すべき部分をご指摘頂きたく存じます。

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

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

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

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

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

guest

回答2

0

自己解決

【結論】テーブルにプライマリーキーが設定されていませんでした。

参考にしたサイトのdbの作成方法を無視し、慣れ親しんだ方法で作成した為、idの列にプライマリーキーを設定していませんでした。SQLITEでは、ある列をプライマリーキーかつINTEGER型としておくと、他の列にデータが入った時、自動的にidに連番が付与される仕組みのようです。これが入っていなかった為、データが読み込めずに表示されなかったというものでした。

この度もご指導誠に有難うございました。

投稿2021/08/30 08:25

編集2021/08/31 05:31
jyansinkai

総合スコア66

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

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

0

動作させてみました。

データが入っていない時はその動作になります。
/createからデータを入力してみてください。

なお、/createから以下を登録した場合、表示は、画像の通りになりました。

title: aaa detail: ddd due: 2021-08-31
title: bbb detail: ccc due: 2021-09-01

Browser image

上記状態のDBのデータは以下の通りでした。(postテーブル。PyCharmで確認)
イメージ説明

データ未入力(dueは入力)の場合は空白文字列が登録され、NULLにはなっていませんでした。
PyCharmでDDLを表示したところ、以下が取得できました。

-- auto-generated definition create table post ( id INTEGER not null primary key, title VARCHAR(30) not null, detail VARCHAR(100), due VARCHAR(20) );

このテーブルはcreate_all()で作成したものなので同じ物だと思いますが、idにNULLが入る要素が無いと思いますので、データ入力に失敗していたりしないか確認ください。

なお、私の環境はWindows 10 + PyCharm Professional + Python 3.8です。
環境が異なる場合、動作が異なる可能性があります。

2021/08/30 18:00追記

以下を設定すると発行されたクエリを見ることができます。

app.config['SQLALCHEMY_ECHO'] = True

実際のクエリを確認すると以下の通りです。

2021-08-30 17:16:14,864 INFO sqlalchemy.engine.Engine BEGIN (implicit) 2021-08-30 17:16:14,865 INFO sqlalchemy.engine.Engine INSERT INTO post (title, detail, due) VALUES (?, ?, ?) 2021-08-30 17:16:14,865 INFO sqlalchemy.engine.Engine [generated in 0.00034s] ('hhh', 'hhh', '2021-08-04') 2021-08-30 17:16:14,867 INFO sqlalchemy.engine.Engine COMMIT 2021-08-30 17:16:14,878 INFO sqlalchemy.engine.Engine BEGIN (implicit) 2021-08-30 17:16:14,879 INFO sqlalchemy.engine.Engine SELECT post.id AS post_id, post.title AS post_title, post.detail AS post_detail, post.due AS post_due FROM post 2021-08-30 17:16:14,879 INFO sqlalchemy.engine.Engine [cached since 12.17s ago] () 2021-08-30 17:16:14,880 INFO sqlalchemy.engine.Engine ROLLBACK
INSERT INTO post (title, detail, due) VALUES (?, ?, ?)

この部分ですが、idが指定されていないINSERTが発行されている事がわかります。

sqliteでINTEGER Primary Keyのカラムに対して値を指定しないでINSERTを行った場合、自動的にrowidが使われるようです。
テーブルの中身が無い場合のrowidがいくつかが明確に書かれているドキュメントを見つけることができませんでしたが、全てのデータを消したテーブルにINSERTしてみると1が設定されたので1から始まるものと考えられます。
値がある場合は最小のrowid + 1が設定されるようです。

/createで値を登録する場合、上記クエリが発行されるので、idにNULLが入る事はなく、1から順番に並んだ値が入る事が分かります。
sqliteの場合primary Key設定をしていても、NULLが入れられるという記事があったので(おかしい気がしますが)、/createを使わず別のツールを使う等の方法で登録すればNULLが入ったデータを設定することが可能です。

投稿2021/08/30 05:52

編集2021/08/30 09:10
FiroProchainezo

総合スコア2421

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

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

jyansinkai

2021/08/30 08:01

ご指導誠に有難うございます。 データベースのidに手動で数字を入力しました所、画面に表示されました。 create.htmlにidを入力する欄は設けていない(参考ページには『自動的に入力される』と書いてあった)のですが、どうしてそちらの環境では自動的にidが入ったのでしょうか…?
FiroProchainezo

2021/08/30 09:11

追記しました。 すでに解決しているようですが。
FiroProchainezo

2021/08/30 09:14

個人的な意見ですが、コメント追加しておいて回答待たずにすぐに自己解決するなら質問すべきではないと思います。 閉まらない質問よりは100倍マシですが。 また、自己解決の「データベースのidにオートインクリメントを設定しておらず、idがNULLとなったデータベースは読まないことが今回の原因でした。」ですが、primary key にNULLが設定できているのを不思議に思っていないのは問題と思います。
jyansinkai

2021/08/31 05:24

ご指導誠に有難うございます。 >>sqliteでINTEGER Primary Keyのカラムに対して値を指定しないでINSERTを行った場合、自動的にrowidが使われるようです。 この仕様は存じませんでした。dbを見直しました所、id列がプライマリーキーに設定されていませんでした。これが設定されていれば、自ずとidが入り、入力内容が表示されたということですね。大変勉強になりました。テーブルを作成する際は必ずプライマリーキーを設定するように致します。 また、回答を待たずに自己解決、ご指導を無にする行為も教わる者としてあるまじき態度でございました。大変失礼致しました。今後とも何卒宜しくお願い申し上げます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.37%

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

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

質問する

関連した質問