Django + microCMSでつくるブログサイト ②記事詳細ページの作成

「Django + microCMSでつくるブログサイト」シリーズの2番目の記事です。
今回は記事詳細ページを実装していきます。

記事詳細コンテンツの取得方法

microCMSでは、APIエンドポイントの後に取得したいコンテンツのIDを指定すると、単体でデータが返ってきます。

例えば、ブログ記事のAPIのエンドポイントをpostとしていたとします。
その中のIDがhogehogeのコンテンツを取得する場合のGET URLは下記のようになります。

https://your-service.microcms.io/api/v1/post/hogehoge


一覧APIの中にもそれぞれの記事のIDが含まれているので、URLに記事IDを引数として渡すイメージです。

URLパターンの追加

Djangoのコードを変更していきます。
シンプルにmicroCMSの記事IDをslugとして記事URLに使用します。

# blog/urls.py

from django.urls import path
from . import views

app_name = 'blog'

urlpatterns = [
    path('', views.post_list, name='index'),
    path('post/<slug:slug>/', views.post_detail, name='post_detail') # 追加
]


viewの追加

次にslugを元にレンダリングを行うviewを追加します。

# blog/views.py

from django.shortcuts import render
import requests
from django.conf import settings
from django.http import Http404 # 追加

def post_list(request):
    """記事一覧"""
    end_point = '/post'
    url = getattr(settings, "BASE_URL", None)
    api_key = getattr(settings, "API_KEY", None)
    headers = {'X-API-KEY': api_key}
    res = requests.request('GET', url=url + end_point, headers=headers)
    context = {
        'post_list': res.json()['contents']
    }

    return render(request, 'blog/index.html', context)

# 追加
def post_detail(request, slug):
    """記事詳細"""
    end_point = f'/post/{slug}'
    url = getattr(settings, "BASE_URL", None)
    api_key = getattr(settings, "API_KEY", None)
    headers = {'X-API-KEY': api_key}
    res = requests.request('GET', url=url + end_point, headers=headers)
	# ステータスコード200以外はエラーなので、404表示
    if res.status_code != 200:
        raise Http404
    context = {
        'post': res.json()
    }

    return render(request, 'blog/post_detail.html', context)


end_pointに受け取ったslugを加えて、GETリクエストを送っています。
以下のような形式でcontextpostに値が渡されます。

{'createdAt': '2021-08-04T13:22:29.259Z',
 'id': 'my-first-blog',
 'publishedAt': '2021-08-04T13:22:29.259Z',
 'revisedAt': '2021-08-04T13:22:29.259Z',
 'text': '<h2 '
         'id="hfd9fd14e3d">最初のブログです</h2><p>microcmsを使った最初のブログです。<br>いろいろなことを書いていきます 。</p>',
 'title': '最初のブログです',
 'updatedAt': '2021-08-04T13:22:29.259Z'}


記事一覧ページの編集

次に記事一覧ページにURLリンクを追記します。

<!-- blog/templates/blog/index.html -->

{% extends "blog/base.html" %}
{% load blog %}

{% load static %}
{% block content %}

<div class="container" style="padding-top:112px;">
  {% for post in post_list  %}
  <article class="article">
    <p class="created-at">{{ post.createdAt | date_from_isoformat }}</p>
	<!-- 追加 post.idとして記事のidをURLに渡す -->
    <a href="{% url 'blog:post_detail' post.id %}">
      <h1 class="post-title" style="margin-top:1rem;">{{ post.title }}</h1>
    </a>
  </article>
  {% endfor %}
</div>
{% endblock %}


記事詳細ページの作成

そして、遷移先である記事詳細ページを作成します。

<!-- blog/templates/blog/post_detail.html -->

{% extends 'blog/base.html' %}
{% load blog %}
{% load static %}
{% block content %}

<div class="container" style="padding-top:112px;">
  <article class="post">
    <p class="created-at">{{ post.createdAt | date_from_isoformat }}</p>
    <h1 class="post-title">
      {{ post.title }}
    </h1>
    <div class="markdown-body">
      {{ post.text }}
    </div>
  </article>
</div>

{% endblock %}


ここまでで、一覧をクリックをすると、詳細ページが表示されます。



htmlタグも文字列として認識されてしまっていますね。
これはautoescapeをoffすることで対処できます。

<!-- blog/templates/blog/post_detail.html -->

	...省略
    <div class="markdown-body">
      {% autoescape off %}
        {{ post.text }}
      {% endautoescape %}
    </div>
	...省略




reset.cssでスタイルを初期化しているのでわかりづらいですが、今日のできごと、に見出しタグが効いていることがわかります。

cssでマークダウンに対応する

microCMSのリッチエディタで書いた記事はマークダウン記法が使えます。
なので、ブログ上でもそれっぽく見えるようにcssを追記していきます。

/* blog/static/css/style.css */

@charset "UTF-8";

...省略

/* --------------------------------
 * 記事詳細
 * -------------------------------- */
.markdown-body {
  margin-top: 5rem;
}

.markdown-body * {
  margin-top: 0;
  margin-bottom: 2rem;
  line-height: 2.0;
  font-size: 1.6rem;
  font-weight: 500;
  font-family: "Yu Gothic Medium", "游ゴシック Medium", YuGothic, "游ゴシック体". "ヒラギノ角ゴ", "ヒラギノ角ゴ Pro W3", sans-serif;
}

.markdown-body strong {
  background-color: yellow;
}

.markdown-body img {
  display: block;
  max-width: 100%;
  margin-top: 20px;
  margin-bottom: 20px;
  height: auto;
  border: solid 1px #ccc;
}

.markdown-body p code {
  background-color: #eee;
  color: #333;
  padding: 0.2em 0.4em;
  font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier, monospace;
  margin-left: 0.5rem;
  margin-right: 0.5rem;
}

.markdown-body pre {
  line-height: 1.2;
  background-color: #1D1F21;
  padding: 2% 4%;
  overflow-x: scroll;
}

.markdown-body pre * {
  margin-bottom: 0;
}

.markdown-body blockquote {
  padding: 15px;
  border-left: 5px solid #ccc;
  border-radius: 2px;
}

.markdown-body h1 {
  font-size: 24px;
  border-bottom: 1px solid #ccc;
  font-weight: bold;
  margin-top: 20px;
  margin-bottom: 10px;
}

.markdown-body h2,
.markdown-body h3 {
  font-size: 20px;
  border-bottom: 1px solid #ccc;
  margin-top: 30px;
  margin-bottom: 10px;
  font-weight: bold;
}

.markdown-body .cp_embed_wrapper {
  margin-top: 20px;
  margin-bottom: 20px;
}

.markdown-body a {
  color: #00809d;
}

.markdown-body a:hover {
  opacity: .5;
}

.markdown-body th {
  font-weight: bold;
  background-color: #3aacad;
  color: #fff;
  border-top: 1px solid

 #ddd;
  border-bottom: 1px solid #ddd;
  border-right: 1px solid #ddd;
  padding: 8px 10px;
}

.markdown-body td {
  border-bottom: 1px solid #ddd;
  border-right: 1px solid #ddd;
  border-left: 1px solid #ddd;
  padding: 8px 10px;
  max-width: 600px;
}

.markdown-body tbody tr {
  background-color: #FAFAFA;
}


また、せっかくマークダウンで記事を書くのであれば、コードをかっこよくハイライトしたいです。
これはhighlight.jsを読み込むのが簡単です。
以下のようにcdnからスタイルシートとjsファイルを読み込んで使います。

<!-- blog/templates/blog/post_detail.html -->

{% extends 'blog/base.html' %}
{% load blog %}
{% load static %}
{% block content %}

<div class="container" style="padding-top:112px;">
  ...省略
</div>

<!-- コードハイライト -->
<link rel="stylesheet" href="//cdn.jsdelivr.net/gh/highlightjs/cdn-release@9.16.2/build/styles/hybrid.min.css">
<script src="//cdn.jsdelivr.net/gh/highlightjs/cdn-release@9.16.2/build/highlight.min.js"></script>
<script type="text/javascript">
  hljs.initHighlightingOnLoad();
</script>

{% endblock %}


今回はhybridテーマを選択して、...hybrid.min.cssの部分で指定をしています。
公式のデモページでいろいろなテーマを見られますので、好みに合わせてテーマを変えると面白いと思います。

実際にmicroCMSから記事を追加します。



ブログ上でこのように表示されます。


ブロック化とSEO対策

ただ、{% block content %}の中に急にJavaScriptのコードが出てくるのはなんだか気持ち悪いですね。
ついでに、ブログであれば、記事に合わせてメタ情報も設定したいです。
例えば記事の詳細とかキーワード等です。

このあたりを記事ごとに動的に設定できるようにしていきます。
まずはbase.html内で、ブロック化して管理をしやすくしていきます。

<!-- blog/templates/blog/base.html -->

{% load static %}

<!doctype html>
<html lang="ja">

<head>
  <!-- Required meta tags -->
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <meta name="keywords" content="{% block meta_keywords %}Django,microCMS,ブログ{% endblock %}">
  <meta name="description" content="{% block meta_descr

iption %}DjangoとmicroCMSで作ったブログです{% endblock %}">
  <title>{% block meta_title %}Django microCMS Blog{% endblock %}</title>
  <link rel="stylesheet" href="{% static "css/reset.css" %}">
  <link rel="stylesheet" href="{% static "css/style.css" %}">
  {% block extrahead %}{% endblock %}
</head>

<body>
  {% include "blog/components/layout-header.html" %}
  {% block content %}{% endblock %}
  
  {% block extrajs %}{% endblock %}
</body>

</html>


microCMSのAPIスキーマの追加

次に記事ごとにキーワードや詳細を設定できるようにmicroCMSのAPIスキーマを編集していきます。

コンテンツ(API)のページに行くと、右上のほうにAPI設定があるのでクリックします。



次にAPIスキーマを選択します。



すると現在のAPI構成ページに遷移します。追加でフィールドを追加できます。



以下のように、descriptionをテキストエリア、keywordsをテキストフィールドで追加しました。



順番はドラッグで簡単に入れ替えることができますので、お好みで並び替えてください。
右下にある変更を押さないと更新されないので注意です。

先ほど書いた記事にアクセスすると、追加した詳細とキーワードが設定できるようになっています。
以下のように追記します。


ブログページへの反映

post_detail.htmlでmicroCMS上で設定した内容を渡すようにします。

<!-- blog/templates/blog/post_detail.html -->

{% extends 'blog/base.html' %}
{% load blog %}
{% load static %}
{% block meta_title %}{{ post.title }} - {{ block.super }}{% endblock %}
{% block meta_description %}{{ post.description }}{% endblock %}
{% block meta_keywords %}{{ post.keywords }}{% endblock %}

{% block content %}

<div class="container" style="padding-top:112px;">
  <article class="post">
    <p class="created-at">{{ post.createdAt | date_from_isoformat }}</p>
    <h1 class="post-title">
      {{ post.title }}
    </h1>
    <div class="markdown-body">
      {% autoescape off %}
      {{ post.text }}
      {% endautoescape %}
    </div>
  </article>
</div>

{% endblock %}

{% block extrajs %}
<!-- コードハイライト -->
<link rel="style

sheet" href="//cdn.jsdelivr.net/gh/highlightjs/cdn-release@9.16.2/build/styles/hybrid.min.css">
<script src="//cdn.jsdelivr.net/gh/highlightjs/cdn-release@9.16.2/build/highlight.min.js"></script>
<script type="text/javascript">
  hljs.initHighlightingOnLoad();
</script>
{% endblock %}


以下のようにmeta情報として認識されるようになります。



次回は記事にタグ付けをしたり、サムネイル画像を表示させて、すこしブログ画面を装飾していこうと思います。

TOPページ