February 16, 2021
←前回:Day 33 画像アップロード機能を付与する
「Djangoを学びたい」とのことでありましたら[Day 1]Djangoの開発環境から読むことをおすすめします。
#はじめに
もうDjnagoの特徴や使い方が大分見えてきましたよね。今回はデータベースに保存されている日時を利用して現在時刻との差分を計算していきます。
#日時オブジェクトのnativeとawareについて
settings.pyにてUSE_TZ = Trueにしている場合タイムゾーンがサポートされます。この状態ではDjangoはタイムゾーンを認識する日時オブジェクト(awareな日時オブジェクト)を使用します。本サイトのようにstartprojectコマンドによってプロジェクトを生成した場合は初期設定としてUSE_TZ=Trueの設定になっています。よって現状ではawareな日時オブジェクトを使用してきました。タイムゾーンが有効となっている場合、データベースにはUTCで日時を保存しています。Djangoはテンプレートやフォーム等で表示する際に、設定されたタイムゾーンで変換をしています。
#データベース
簡単にデータベースについて触れておきたいと思います。本筆者としてはタイムゾーンは常に有効にして使用した方が良いと考えていますが、タイムゾーンの有効・無効を切り替える場合もあると思います。PostgreSQLはタイムゾーン情報をデータベースに保存しているために、タイムゾーンの有効・無効は自由に切り替えられます。しかしそれ以外のデータベースに関してはタイムゾーンがを無効に切り替えた場合にはUTCからネイティブなdatetimeに変換する必要があります。
#現在時刻との差分を計算してNEWラベルをつける
さて、今回は演習として一時間以内に新しく作成されたトピックはトップページにNEWラベルを表示するようにしましょう。トップページを表示しているビューはbase/views.pyのTopicListViewクラスですので、ここに手を加えていきます。
from django.utils import timezone
class TopicListView(ListView):
template_name = 'base/top.html'
# model = Topic
queryset = Topic.objects.order_by('-created')
context_object_name = 'topic_list'
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.new_list = []
def get_queryset(self):
topic_list = Topic.objects.order_by('-created')
self.new_list = self._make_new_list(topic_list)
return topic_list
def get_context_data(self, **kwargs):
ctx = super().get_context_data(**kwargs)
ctx['new_list'] = self.new_list
return ctx
def _make_new_list(self, topic_list):
def pickup_topic(topic):
now = timezone.now()
diff = (now - topic.created).total_seconds() / (60 * 60)
if diff > 1:
return False
else:
return True
return list(map(lambda x : x.id ,filter(pickup_topic, topic_list)))
解説は不要かと思いますが、現在時刻をtimezone.now()で取得してデータベースに格納されているtopic.createdと差を求めて秒を時間に変換しています。この時間が1時間以下のトピックのIDのみのリストを作成して返していますね。コンテキストにnew_listを渡すためnew_listをインスタンス変数として渡しています。
ラベルを表示するようにテンプレートも変更しましょう。
{% extends 'base/base.html' %}
{% block title %}ITについて切磋琢磨する掲示板 - {{ block.super }}{% endblock %}
{% block content %}
<div class="ui grid stackable">
<div class="eleven wide column">
<div class="ui breadcrumb">
<a class="active section">TOP</a>
</div>
<div class="ui segment">
<div class="content">
<div class="header"><h3>新着スレッド</h3></div>
<div class="ui divided items">
{% for topic in topic_list %}
<div class="item">
<div class="content">
<div class="header">
<a href="{% url 'thread:topic' pk=topic.id %}">
<h4>
{% if topic.id in new_list %}
<div class="ui violet horizontal label">new</div>
{% endif %}
{{topic.title}}
</h4>
</a>
</div>
<div class="meta">
<span class="name">{{topic.user_name}}</span>
<span class="date">{{topic.created}}</span>
</div>
</div>
</div>
{% endfor %}
</div>
</div>
</div>
</div>
{% include 'base/sidebar.html' %}
</div>
{% endblock %}
全て掲載しましたが、修正点はトピックタイトルの部分のみです。
では確認してみましょう。新規にトピックを作成するとNEWラベルがつきますね。
#おわりに
お久しぶりです。復活しました。Django学習帳が使えなくなってから、体調が悪くなってしまいました。あと、履歴書書いていました。
今日からまた頑張っていきたいと思います。
それではまたまた