「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を引数として渡すイメージです。
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') # 追加
]
次に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リクエストを送っています。
以下のような形式でcontext
のpost
に値が渡されます。
{'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でスタイルを初期化しているのでわかりづらいですが、今日のできごと、に見出しタグが効いていることがわかります。
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から記事を追加します。
ブログ上でこのように表示されます。
ただ、{% 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スキーマを編集していきます。
コンテンツ(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情報として認識されるようになります。
次回は記事にタグ付けをしたり、サムネイル画像を表示させて、すこしブログ画面を装飾していこうと思います。