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

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

ただいまの
回答率

90.51%

  • Python 3.x

    8901questions

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

  • Django

    1454questions

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

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

解決済

回答 1

投稿

  • 評価
  • クリップ 0
  • VIEW 75

akbr

score 1

前提・実現したいこと

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

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

+1

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

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

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

views.py:
// クライアントサイドから渡された対象年月を取得
// 対象年月の model の queryset を取得

// ★: 対象年月の日付一覧を取得
// ★: queryset に対してループを回して、「日付: イベント一覧」のデータを作成

// 「日付: イベント一覧」のデータを template に渡す

template:
// view から渡された「日付: イベント一覧」のデータに対してループを回しカレンダーを描画

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

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/03/15 13:50 編集

    ※すみません、コードブロックの書き方がヘルプを見てもわからず、体裁崩れてみえます
    ご回答ありがとうございます。
    頂いたサンプルですと、日付一覧を取得した際に存在しないデータがあった場合抜けた状態で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 %}
    ```

    キャンセル

  • 2019/03/15 14:33 編集

    なるほど、「データが存在しない日の場合でも、データが存在する日と同様のテンプレートを、デフォルト値等を含めて表示したい」ということだったのですね。

    もう少し具体的な要件がわからないと踏み込んだ議論は難しいですが、「デフォルト値をテンプレート側に書きたくない」ということであれば、後は view 側でデフォルトデータを用意する(= model インスタンスを作る)しかオプションが無さそうですよね。ということで、載せられたコードの方向性でよいのではないでしょうか。ただし、データが無いすべての日付に対して別のインスタンスを用意する必要は無いと思いので、「空の日用のインスタンス」をひとつだけ作っておいて、それを使い回せばよいと思います。いずれにせよ、データの有無によらずテンプレートを共通化させたい & テンプレート側で `pk` を使いたいということであれば、少なくとも `pk` 周りではテンプレート内での分岐は必要になってくるのではないでしょうか。

    見かけ上テンプレートをスッキリさせたいのであれば、別のオプションとして、カスタムテンプレートタグあるいはテンプレートフィルタを作る、というアプローチもありだと思います(特に、同様のパターンを複数のテンプレートで使い回すのであれば、テンプレートタグを用意した方がよいケースが多いのではないでしょうか)。

    > views.pyでmodelインスタンスを作るならそれはDBに存在しないとけない、みたいなフレームワークの思想があるのではと考えています

    こちらについては、私の認識ではそのような思想は無いと思っています。そのお考えを持たれるに至った情報源がもしあればご提示ください。その認識を共有した上で議論をさせていただけるものと思います :D

    キャンセル

  • 2019/03/18 10:57

    ・空データ(デフォルトデータについて)
    なるほど、この方向性で良さそうならもっと色々試行錯誤してみたいと思います。
    pk周りの分岐はしょうがないですね、カスタムテンプレートタグについてはまだ調査できていませんが、他フレームワークであるような機能だと思うので作ってみたいと思います。

    ・modelインスタンスを作るとDBに存在しないといけないかについて
    そのような認識がない、とのことで、つまり私の試行錯誤で別のところに問題があったということなのかもしれません。
    私がそう思ったのは、明記されているわけではありませんが、
    ネット上で見つかるviewのサンプルがすべて、「DBに存在するものを渡す」ものしかなくて「Viewでインスタンスを生成して渡す方法」が見つからないから、なのと、
    Viewでインスタンスを作成するとpkに関するエラーやよくわからないエラーが出て先に進めないから、です。

    ・・・と、試行錯誤しながら文章書いていたら今少し進みました!
    pkのないインスタンスがあるためにtemplateのhtml内にあるpkを使うリンクをコメントアウト(<!---->)していたのですがそれでエラーがずっと出ていました。
    どうやらdjangoではコメントアウトされたリンクでも妥当性チェックがされていたようです。
    行を完全に削除したらエラーが解消されました。

    「私の認識ではそのような思想は無いと思っています」とのご回答のおかげです。
    方向性は良さそうとのことでしたのでこのまま頑張ってみようと思います。
    一旦今回の質問は解消されましたので解決とさせていただきます。
    周りでプログラミングで質問できる相手が居ない中で大変助かりました、ありがとうございました。

    キャンセル

  • 2019/03/19 21:16

    とてもご丁寧にコメントお戻しくださりありがとうございます。

    > 他フレームワークであるような機能だと思うので...

    そうですね、おそらくご認識のとおりだと思いますので、いちどお調べになってみてください。

    > 私がそう思ったのは、明記されているわけではありませんが、...

    なるほど、そういうことですね!

    ちなみに、 `{% url route_name daydata.pk %}` のパターンで出ているエラーは、ご存知のとおり model が DB に保存されるまでは `pk` の値が `None` になっていることが原因です。ここは、 model がエラーを起こしているのではなく、テンプレートタグ `url` でエラーが出ているので、そのことを頭に入れておくと、テンプレートの見通しがよくなる(=テンプレートで何に注意すればよいのかがはっきりする)かと思います。

    前進されているとのことでよかったです :) がんばってください。

    キャンセル

同じタグがついた質問を見る

  • Python 3.x

    8901questions

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

  • Django

    1454questions

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