こんにちは、工学部生のShinonです。 自作のポートフォリオサイトを運用し始めて少し経ち、Googleアナリティクスでアクセス解析をしてみました。
すると、ありがたいことにトップページ(GALLERY)へのアクセス数は増えているものの、「そこからブログ記事へ飛んでくれる人が少ない」という課題が見えてきました。 せっかく書いた物品紹介や自作ドローンの記事をもっと読んでもらうため、トップページの一番目立つ場所に「今、読まれている人気記事」をランキング形式で表示する機能を実装しました。
今回は、Djangoを使って「記事の閲覧数をカウントする仕組み」と「上位3件を取得してトップページに表示する仕組み」の実装手順を解説します。
1. 記事モデルに「閲覧数」のカウント用フィールドを追加
まずはデータベースの設計図である models.py に、「どの記事が何回読まれたか」を記録するシステムを作ります。
models.py の修正
既存のブログ記事のモデル(Post)に、閲覧数を保存する views という整数フィールドを追加しました。 マイナスになることはないので、PositiveIntegerField を使っています。
class Post(models.Model): # (中略) content = HTMLField("本文") # ▼ 追加:人気記事表示のための閲覧数カウント views = models.PositiveIntegerField("閲覧数", default=0)
※追加後は makemigrations と migrate を忘れずに実行してデータベースを更新します。
2. クラスベースビューで閲覧数をカウントアップ
次に、「ブログの詳細ページが開かれた瞬間に、閲覧数を1増やす」という処理を書きます。 関数ベースで書いても良いのですが、今回は DetailView を使っているので、裏側でデータを取り出す get_object メソッドをオーバーライド(上書き)しました。
views.py の修正(詳細ページ)
class PostDetailView(DetailView): model = Post template_name = 'photos/post_detail.html' def get_object(self, queryset=None): # 1. まず通常通り記事のデータを取得する obj = super().get_object(queryset=queryset) # 2. 閲覧数に1を足す obj.views += 1 # 3. データベースに保存(viewsだけを更新して負荷を減らす) obj.save(update_fields=['views']) return obj
ここでポイントなのが、save(update_fields=['views']) と指定している点です。こうすることで、巨大な画像データや本文などを毎回保存し直すことなく、「閲覧数の数字だけ」を効率よくデータベースに書き込むことができます。
3. トップページに「上位3件」のデータを渡す
閲覧数がカウントできるようになったので、あとはトップページを表示するビュー関数で「閲覧数が多い順に並び替えて、上から3つだけ取得」してテンプレートに渡します。
views.py の修正(トップページ)
def index(request): posts = PhotoPost.objects.all().order_by('-created_at') # ▼ 追加:人気記事(ブログ)を閲覧数順(降順)に3件取得 popular_posts = Post.objects.order_by('-views')[:3] return render(request, 'photos/index.html', { 'posts': posts, 'popular_posts': popular_posts, # テンプレートへ渡す })
order_by('-views') のようにフィールド名の前に -(マイナス) をつけることで、「大きい順(降順)」に並び替えることができます。最後に [:3] でスライスすれば、TOP3の抽出は完了です。
4. テンプレートでのスマートな抜粋表示
最後に、トップページの index.html に受け取ったデータを表示させます。 ブログの本文をそのまま出力すると長すぎるため、Djangoの便利なテンプレートフィルターを組み合わせてカード型のプレビューを作りました。
index.html(抜粋部分)
<div class="card-body"> <h5 class="card-title">{{ blog.title }}</h5> <p class="card-text text-muted"> {{ blog.content|striptags|truncatechars:50 }} </p> <small class="text-muted fw-bold"> {{ blog.views }} views</small> </div>
{{ blog.content|striptags|truncatechars:50 }} は非常に便利です。 私のブログはTinyMCEを使っており本文にHTMLタグが含まれているのですが、まず striptags で文字だけを綺麗に抽出し、その上で truncatechars:50 を使って「最初の50文字以降を『…』で省略する」という処理を1行で実現しています。
まとめ
アクセス解析(Googleアナリティクス)で見えた「回遊率」という課題に対し、Djangoの機能をフル活用してUIを改善することができました。
モデルの追加、ビューでの効率的なカウント、そしてテンプレートフィルターでの成形。Webフレームワークの強みを活かしてサクッと機能追加できると、開発のモチベーションがさらに上がります。新しくなったトップページ「GALLERY」から、ぜひ色々な記事を覗いてみてください。
