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

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

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

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

Python 3.x

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

Q&A

解決済

1回答

495閲覧

Django 存在しないデータをHTMLに送る方法

akbr

総合スコア88

Django

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

Python 3.x

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

0グッド

0クリップ

投稿2019/03/14 16:51

前提・実現したいこと

Python Djangoを勉強中です。公式チュートリアルをこなした程度の状態です。
日毎のデータを格納するModelを定義して、それをカレンダーのように1月分一覧表示したいです。
その一覧画面では日毎のデータを選択して個別の日毎データの編集画面に遷移したいです。

全ての日付に日毎データがあるのであれば、
Viewsクラスで1ヵ月分のクエリーを作ってそれで得られたModelインスタンスリストをQuerySetにセットしてやればよいです。

しかし最初は日毎データが存在しないのでクエリーだと当然0件もしくは入力したことのある日付の日毎データだけがQuerySetにセットされます。それをカレンダー表示しようと思ったら単純に考えるとHTMLの方で1ヵ月分のデータが揃っているか、揃っていないなら空行を表示する、ようなコーディングが必要になります。
できればサーバーロジック側で処理したいので、まずはQuerySetの中にダミーデータ(DBには存在しない空行データ)を差し込んでやろうというアプローチで考えましたが、QuerySetにデータを入れるにはどうもpkが必要?みたいでうまくいきませんでした。ネット上にもサンプルは見つけられませんでした。
クエリの段階で足りない日付データインスタンスをcreateしてやれば多分うまくいくのですが、この方法だと本来データが存在しない日付のデータがDB上に登録されてしまうと思います。しかも表示のクエリの段階で。

次に、QuerySetではなく、コンテキストデータとしてModelインスタンスのリストでも返してやろうと思いましたが、この方法でもpkエラーが発生してしまいます。恐らく一覧画面から日毎データの詳細画面か編集画面へのリンクのところでpkを使っているからです。

今回のような場合、Djangoではどのようなアプローチで実現するのが妥当でしょうか。ヒントを頂きたく、、、
また、今回のようなこういう場合はどうすれば?という疑問がネット検索では一切解決しないので、ヒントとは別に書籍や調べ方の紹介もして頂ければ幸いです。
よろしくお願いいたします。

補足情報(FW/ツールのバージョンなど)

Python 3.7.0
Django 2.1.4

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

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

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

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

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

guest

回答1

0

ベストアンサー

「日毎のデータを格納する model があって、その一覧を月単位で表示したい」ということですね。

私の理解が間違っていなければ、難しく考えすぎていらっしゃるのではないかと思います。 Django では、というよりはプログラミングの一般論としてのお話になりますが、 model の一覧(= queryset )からカレンダー形式のデータを構築するためのループを書けばよいのではないかと思います。

擬似コードは次のような感じになるでしょうか( ★の部分が上の「ループ」です)。

text

1views.py: 2// クライアントサイドから渡された対象年月を取得 3// 対象年月の model の queryset を取得 4 5// ★: 対象年月の日付一覧を取得 6// ★: queryset に対してループを回して、「日付: イベント一覧」のデータを作成 7 8// 「日付: イベント一覧」のデータを template に渡す 9 10template: 11// view から渡された「日付: イベント一覧」のデータに対してループを回しカレンダーを描画

(実際に書かれたコードを掲載されると、具体的なヒントがもらえやすくなると思います)

投稿2019/03/15 04:01

gh640

総合スコア1407

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

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

akbr

2019/03/15 04:58 編集

※すみません、コードブロックの書き方がヘルプを見てもわからず、体裁崩れてみえます ご回答ありがとうございます。 頂いたサンプルですと、日付一覧を取得した際に存在しないデータがあった場合抜けた状態でtemplate側に渡すという意味だと思います。 そうするとtemplate側で存在確認→ないならデフォルト値をセット(場合によっては何らかの算出処理も)、とすることになると思います。 そういう処理をtemplate側に書くのはどうなのかな、という考えからの質問になります。 で、仮にtemplateで書くべきではなくViews.pyあたりで書いた方がいいとなった場合、Djangoでその時点で存在しない空データインスタンスをどう作ってどうtemplateに送ればいいのか?と思った次第です。 試した限りエラーエラーでどうにもなりませんでした。恐らく、views.pyでmodelインスタンスを作るならそれはDBに存在しないとけない、みたいなフレームワークの思想があるのではと考えています。 もしtemplate側で存在確認やデフォルト値設定処理をやった方がいいというなら、試してませんがおっしゃる通りのやりかたで実現できると思います。 実装中のコードはこんなイメージになります views.py ```lang-Plain text def get_monthly_list(self): first_date = date(2019, 3, 1) last_date = date(2019, 4, 1) queryset = Daydata.objects.filter(daydata_at__range=(first_date, last_date)).order_by('created_at') resultset = [] for i in daterange(first_date, last_date): daydata = queryset.filter(daydata_at=i) if daydata .count() == 1: row = daydata else: row = Daydata(daydata _at=i) resultset.append(row) return list(resultset) ``` urls.py ```lang-Plain text path('', DaydataFilterView.as_view(), name='index'), ``` daydata_filter.html(html略、viewsで悩んでいるので未完成) ```lang-Plain text {% for daydata in monthly_list %} daydataの各項目をアウトプット <a href="{% url 'detail' daydata.pk %}">詳細</a> <a href="{% url 'update' daydata.pk %}">編集</a> <a href="{% url 'delete' daydata.pk %}">削除</a>            ↑空データにはまだpkがないのでそこもどうにかしないといけない {% endfor %} ```
gh640

2019/03/15 05:39 編集

なるほど、「データが存在しない日の場合でも、データが存在する日と同様のテンプレートを、デフォルト値等を含めて表示したい」ということだったのですね。 もう少し具体的な要件がわからないと踏み込んだ議論は難しいですが、「デフォルト値をテンプレート側に書きたくない」ということであれば、後は view 側でデフォルトデータを用意する(= model インスタンスを作る)しかオプションが無さそうですよね。ということで、載せられたコードの方向性でよいのではないでしょうか。ただし、データが無いすべての日付に対して別のインスタンスを用意する必要は無いと思いので、「空の日用のインスタンス」をひとつだけ作っておいて、それを使い回せばよいと思います。いずれにせよ、データの有無によらずテンプレートを共通化させたい & テンプレート側で `pk` を使いたいということであれば、少なくとも `pk` 周りではテンプレート内での分岐は必要になってくるのではないでしょうか。 見かけ上テンプレートをスッキリさせたいのであれば、別のオプションとして、カスタムテンプレートタグあるいはテンプレートフィルタを作る、というアプローチもありだと思います(特に、同様のパターンを複数のテンプレートで使い回すのであれば、テンプレートタグを用意した方がよいケースが多いのではないでしょうか)。 > views.pyでmodelインスタンスを作るならそれはDBに存在しないとけない、みたいなフレームワークの思想があるのではと考えています こちらについては、私の認識ではそのような思想は無いと思っています。そのお考えを持たれるに至った情報源がもしあればご提示ください。その認識を共有した上で議論をさせていただけるものと思います :D
akbr

2019/03/18 01:57

・空データ(デフォルトデータについて) なるほど、この方向性で良さそうならもっと色々試行錯誤してみたいと思います。 pk周りの分岐はしょうがないですね、カスタムテンプレートタグについてはまだ調査できていませんが、他フレームワークであるような機能だと思うので作ってみたいと思います。 ・modelインスタンスを作るとDBに存在しないといけないかについて そのような認識がない、とのことで、つまり私の試行錯誤で別のところに問題があったということなのかもしれません。 私がそう思ったのは、明記されているわけではありませんが、 ネット上で見つかるviewのサンプルがすべて、「DBに存在するものを渡す」ものしかなくて「Viewでインスタンスを生成して渡す方法」が見つからないから、なのと、 Viewでインスタンスを作成するとpkに関するエラーやよくわからないエラーが出て先に進めないから、です。 ・・・と、試行錯誤しながら文章書いていたら今少し進みました! pkのないインスタンスがあるためにtemplateのhtml内にあるpkを使うリンクをコメントアウト(<!---->)していたのですがそれでエラーがずっと出ていました。 どうやらdjangoではコメントアウトされたリンクでも妥当性チェックがされていたようです。 行を完全に削除したらエラーが解消されました。 「私の認識ではそのような思想は無いと思っています」とのご回答のおかげです。 方向性は良さそうとのことでしたのでこのまま頑張ってみようと思います。 一旦今回の質問は解消されましたので解決とさせていただきます。 周りでプログラミングで質問できる相手が居ない中で大変助かりました、ありがとうございました。
gh640

2019/03/19 12:16

とてもご丁寧にコメントお戻しくださりありがとうございます。 > 他フレームワークであるような機能だと思うので... そうですね、おそらくご認識のとおりだと思いますので、いちどお調べになってみてください。 > 私がそう思ったのは、明記されているわけではありませんが、... なるほど、そういうことですね! ちなみに、 `{% url route_name daydata.pk %}` のパターンで出ているエラーは、ご存知のとおり model が DB に保存されるまでは `pk` の値が `None` になっていることが原因です。ここは、 model がエラーを起こしているのではなく、テンプレートタグ `url` でエラーが出ているので、そのことを頭に入れておくと、テンプレートの見通しがよくなる(=テンプレートで何に注意すればよいのかがはっきりする)かと思います。 前進されているとのことでよかったです :) がんばってください。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問