Help us understand the problem. What is going on with this article?

Djangoで時間経過が見やすい体験紹介サービスを作った話

実行環境

macOS Catalina
Python3.7
Django2.1.8
(Djangoの最新バージョンは3.0ですがGAEでデプロイする時にデータベースをMySQLを利用する場合、依存するライブラリのPyMySQLがDjango2.2系に対応していないため、当記事ではDjango2.1.8を利用しています。)

作ったもの

実際にデプロイ作業まで行ったので良かったら見てください。
[関東とっておきプロジェクト]
https://kanto.dev/

謝辞

はじめに、下記のgithubのソースコードの一部を利用させて頂きました。
この場をお借り致しましてお礼申し上げます。ありがとうございました。
https://github.com/naritotakizawa/django-simple-calendar

概要

この記事の内容はタイトルの通りですが、具体的には自分が開発中に躓いた箇所をまとめたものです。

躓いたポイント

  • データベースの値を弄って(計算して)、cssの値を変更させる
  • DateTimeFieldとタイムゾーンの扱い
  • データベース上の定休日の考え方
  • Google Map JavaScript APIにDjangoのデータベースに登録された値を展開する

データベースの値を計算して、cssの値を変更させる

自分の中で最終的な最適解はモデルメソッドを作ることです。私が知らなかった技術というか気づけば当然の事ですが、データベースの値を書き換える必要は無くテンプレートで扱う値を変えたい場合、モデルメソッドを生やすというのが単純で簡単です。具体的には以下のような形で実装しました。(経過時間分を左から右にずらす場合)

models.py
def ratio_time(self, date):
    return ( 60*date.hour + date.minute ) / ( 60*24 )

def create_margin_left(self):
    return str( self.ratio_time(self.FIELD + timedelta(hours=9)) * 100) + "%"
template.html
<div style="margin-left: {{ OBJECT.create_margin_left }}; width: 10px; height: 5px;"></div>

DateTimeFieldとタイムゾーンの扱い

このDatetimeFieldの扱いとして、最初の勘違いはタイムゾーンを保持していないということです。つまり、テンプレート内で仮に日本時間で扱いたい場合は、これをイギリス時間にtimezone分(+9時間)を設定しなくてはなりません。当初、Djangoプロジェクト内のsettings.pyで記述したtimezone='Asia/Tokyo'が適用されて上手くやってくれると思っていましたが、違っていたようです。また、テンプレート内で表示形式を変更する場合や、タイムゾーンを付けたり消したりしたい場合にはこちらをご覧ください。

[Pythonのdatetime型の扱い]
https://docs.python.org/ja/3/library/datetime.html

[Djangoのtimezoneの扱い]
https://docs.djangoproject.com/en/2.2/topics/i18n/timezones/

データベース上の定休日の考え方

この考え方を知る前と知った後では新しい考え方が身につきました。定休日はその日が空いてる・空いていないの1Bitの情報が7つ分連なっているだけに過ぎません。つまり、データベース上では7bitのIntegerField(0~127)までを扱えれば済む訳です。0bit目を日曜日として扱う場合、0010001は火曜日と土曜日が定休日という感じで扱えます。割とよく使われるみたいなので覚えておいて損はないと思います。(ただし、実装は若干難しくなります。)

[考え方について]
https://lambdalisue.hatenablog.com/entry/2013/12/22/041347
[実装中に参考になったURL]
https://stackoverflow.com/questions/9921221/how-to-perform-db-bitwise-queries-in-django

Google Map JavaScript APIにDjangoのデータベースに登録された値を展開する

筆者はエディタ(Visual Studio Code)を利用しているのですが、そこでコード整形等の見た目を整える拡張機能を入れています。プラグインによってはJavaScriptのように整形するツールがあり使用すると、before.htmlのようになることがあります。しかし、テンプレート内でDjangoのデータを扱う場合は必ず{{ FIELD_NAME }}のようにする必要があります。適切なコードフォーマットを利用しないと値を読み込めなくなりますので、気をつけましょう。

before.html
<script>
var latitude = {
    {
        OBJECT.latitude
    }
};
var longitude = {
    {
        OBJECT.longitude
    }
}
</script>
after.html
<script>
    var latitude = {{ OBJECT.latitude }};
    var longitude = {{ OBJECT.longitude }};
</script>

その他の躓いた点

CSSが実装出来ているのか不明だったので、確認作業を行っていたが、横幅しか気にしていなくて、縦幅を設定をし忘れていた。色を表示させたりする場合、横幅だけでなく縦幅も設定しないと視覚的に変化はない。

まとめ

  • カレンダーの実装はタイムゾーンを意識する必要があるが、データベース自体を変更しない場合は割と簡単に扱えることがわかった。(モデルメソッドを使う)
  • 定休日を実装する場合、少し検索すると各曜日にFieldを追加(合計で7つ)して、実装するものが多かったが、ON-OFFのような1bitで表せる情報を複数同時に扱う効率的なやり方を知れた。
  • プラグインは用量・用法を適切に使うべき。

当記事で誰か1人のエラーや疑問解消の一助になれば幸いです。

toppo_toc
都内の某大学に通っている大学生。趣味で競プロ(Atcoder)をやっています。(言語はPython) ラーメンと酪王カフェオレが大好き。
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away