「Django + microCMSでつくるブログサイト」の最初の記事です。
今回は環境設定から記事一覧ページの作成までをまとめます。
まずはmicroCMS側の設定をしていきます。
登録がまだの方は公式ブログを参照するとわかりやすいです。この記事ではサービス情報の登録から説明をしていきます。
登録が完了しましたら、サービスを作成します。
とりあえず以下のようにしました。
サービスIDは他の人とは重複して使用できないので、何か違うものを入力してください。
次にサービス画像を選択
という画面が出てきますが、こちらは飛ばして大丈夫です。
その後、料金プランの選択画面が出ます、無料のhobby
プランを選択しましょう。
進めていくとAPIの基本情報を入力する画面が出てきます。
今回はブログを作成するので、API名を記事、エンドポイントをpost
と入力しました。
リスト形式
を選択します。
APIスキーマの入力画面に移ります。
ここで、ブログにどんな情報を持たせたいか?ということを定義していきます。
とりあえず、タイトルと本文を設定します。 こちらの設定は後から追加・変更が簡単にできます。
本文に割り当てたリッチエディタはマークダウン記法に対応しています。 Djangoモデルでブログサイトを作る場合、マークダウン記法に対応させるのが少し手順が多いので、うれしいポイントです。
管理画面の右上にある追加
ボタンを押すと、記事が追加できます。
コンテンツID
は初期表示でランダム文字列が割り振られるので、以下のように変えました。
公開
を押すと投稿がされます。
トップページに戻ると、きちんと公開されていることが分かります。
Django側での記事の取得に必要なAPIキーを確認していきます。
管理画面の右上のAPI設定
をクリックします。
遷移したページでAPIリファレンス
と続けます。
次の画面でX-API-KEY
が表示されているかと思います。
こちらをのちに使うので、メモしておきましょう。
また、リクエストURLの共通部分はhttps://your-service-id.microcms.io/api/v1
となります。
私の場合はdjango-microcms
と入力していたので、https://django-microcms.microcms.io/api/v1
ですね。
こちらものちに必要になりますので、メモしておきす。
次にdjango側の設定をしていきます。 適当なフォルダを作り、仮想環境をactivateします。
mkdir django-microcms
cd django-microcms
python -m venv myvenv
myvenv\\scripts\\activate
django
とrequests
をpipでinstallします。
pip install django
pip install requests
djangoのプロジェクトとアプリをスタートしましょう。 最後の.
を忘れないようにします。
django-admin startproject project .
python manage.py startapp blog
とりあえず組み込みモデルをmigrate
して、superuserも作っておきましょう。
python manage.py migrate
Operations to perform:
Apply all migrations: admin, auth, contenttypes, sessions
Running migrations:
Applying contenttypes.0001_initial... OK
Applying auth.0001_initial... OK
Applying admin.0001_initial... OK
...省略
python manage.py createsuperuser
ここまでで、コマンドラインは終わりです。 次にソースコードを書いていきます。
settings.py
を以下のように編集します。
# project/settings.py
...省略
INSTALLED_APPS = [
'blog.apps.BlogConfig', #追加
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
]
...省略
LANGUAGE_CODE = 'ja'
TIME_ZONE = 'Asia/Tokyo'
...省略
STATIC_URL = '/static/'
#追加
STATIC_ROOT = Path(BASE_DIR, 'static')
API_KEY='your api key'
BASE_URL='your microcms request url'
先ほど保存したAPIキーとリクエストURLをsettings.py内に書いておきましょう。
次にurls.py
です。
#project/urls.py
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('blog.urls'))
]
まずはアプリ内のurls.py
にurlパターンを定義します。 現状は記事一覧のみです。下のようにします。
#blog/urls.py
from django.urls import path
from . import views
app_name = 'blog'
urlpatterns = [
path('', views.post_list, name='index'),
]
次にviews.py
の編集します。
ここでrequests
ライブラリを使用して、microCMSで先ほど作成した記事を呼び出す、という流れです。
microCMSのコンテンツはヘッダーを{'X-API-KEY':apiキー}
として、GETリクエストを送ると取得できます。
ためしにコマンドラインに取得情報を表示させてみましょう。
#blog/views.py
from django.shortcuts import render
import requests
from django.conf import settings
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)
from pprint import pprint
pprint(res.json())
ローカルサーバーを起動させます。
python manage.py runserver
http://127.0.0.1:8000/
にアクセスすると、エラー画面が出ると思いますが、コマンドラインに先ほど書いた記事がプリントされます。
{'contents': [{'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'}],
'limit': 10,
'offset': 0,
'totalCount': 1}
記事の内容が取得できていることがわかります。 あとはcontextにcontents
以下を渡して表示させるという流れです。 以下のように書き換えます。
#blog/views.py
...省略
def post_list(request):
"""記事一覧"""
...省略
res = requests.request('GET', url=url + end_point, headers=headers)
context = {
'post_list': res.json()['contents']
}
return render(request, 'blog/index.html', context)
次に表示させるhtmlファイルを作成していきます。 blogディレクトリ以下にtemplates
、そのなかにblog
ディレクトリを作成します。
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">
<title>Django microCMS Blog</title>
</head>
<body>
{% block content %}{% endblock %}
</body>
</html>
次にこちらを読み込む形で、記事一覧を表示するindex.html
を作成します。
<!-- blog/templates/blog/index.html -->
{% extends "blog/base.html" %}
{% load static %}
{% block content %}
{% for post in post_list %}
<article class="article">
<p>{{ post.createdAt }}</p>
<h1>{{ post.title }}</h1>
</article>
{% endfor %}
</div>
{% endblock %}
装飾をしていないので、非常に味気ないですが、とりあえずは表示できました。
microCMSから二つ目の記事を追加してみましょう。 内容はなんでも大丈夫です。
そうすると、以下のように一覧画面に記事が追加されます。
このままだとタイトルと日付だけなので、簡単な装飾を施していきます。
blog/templates
配下にcomponents
フォルダを作り、layout-header.html
を作成します。
<!-- blog/templates/components/layout-header.html -->
<header class="header">
<h1 class="">
<a href="{% url 'blog:index' %}" class="page-title">Django microCMS Blog</a>
</h1>
<nav class="nav">
<ul class="main-nav">
<li><a href="{% url 'blog:index' %}">HOME</a></li>
</ul>
</nav>
</header>
次に作成したヘッダーを読み込みます。 ついでにこれから作るcssの読み込みの記述も行っておきましょう。
<!-- blog/templates/blog/base.html -->
{% load static %}
<!doctype html>
<html lang="ja">
<head>
<!-- 追加 -->
<link rel="stylesheet" href="{% static "css/reset.css" %}">
<link rel="stylesheet" href="{% static "css/style.css" %}">
</head>
<body>
<!-- ヘッダーの読み込み -->
{% include "blog/components/layout-header.html" %}
{% block content %}{% endblock %}
</body>
</html>
microCMSからの日付データはISO 8601形式のUTC(協定世界時)にて返却されます。
これをyyyy-mm-dd
形式に変えたいです。 色々方法はあると思うのですが、自作フィルタを作成して対応します。
temlates
フォルダにtemplatetags
ディレクトリを作り、blog.py
を作成します。
協定世界時は日本時間から9時間前なので、一旦datetime型に直してから、9時間分足します。
from django import template
import datetime
register = template.Library()
@register.filter
def date_from_isoformat(date_string):
"""UTC時刻をyyyy-mm-ddに置き換える"""
d = datetime.datetime.fromisoformat(date_string[:-1])
d += datetime.timedelta(hours=9)
return datetime.datetime.strftime(d, "%Y-%m-%d")
次に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>
<h1 class="post-title" style="margin-top:1rem;">{{ post.title }}</h1>
</article>
{% endfor %}
</div>
{% endblock %}
最後にcssで装飾していきます。
blog
配下にstatic/css
というディレクトリを作りcssファイルを作成します。
reset.css
とstyle.css
です。
/* blog/static/css/reset.css */
/**
* html5doctor.com Reset Stylesheet v1.6.1 (<http://html5doctor.com/html-5-reset-stylesheet/>)
* Richard Clark (<http://richclarkdesign.com>)
* <http://cssreset.com>
*/
html, body, div, span, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
abbr, address, cite, code,
del, dfn, em, img, ins, kbd, q, samp,
small, strong, sub, sup, var,
b, i,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td,
article, aside, canvas, details, figcaption, figure,
footer, header, hgroup, menu, nav, section, summary,
time, mark, audio, video {
margin:0;
padding:0;
border:0;
outline:0;
font-size:100%;
vertical-align:baseline;
background:transparent;
}
body {
line-height:1;
}
article,aside,details,figcaption,figure,
footer,header,hgroup,menu,nav,section {
display:block;
}
nav ul {
list-style:none;
}
blockquote, q {
quotes:none;
}
blockquote:before, blockquote:after,
q:before, q:after {
content:'';
content:none;
}
a {
margin:0;
padding:0;
font-size:100%;
vertical-align:baseline;
background:transparent;
}
/* change colours to suit your needs */
ins {
background-color:#ff9;
color:#000;
text-decoration:none;
}
/* change colours to suit your needs */
mark {
background-color:#ff9;
co
lor:#000;
font-style:italic;
font-weight:bold;
}
del {
text-decoration: line-through;
}
abbr[title], dfn[title] {
border-bottom:1px dotted;
cursor:help;
}
table {
border-collapse:collapse;
border-spacing:0;
}
/* change border colour to suit your needs */
hr {
display:block;
height:1px;
border:0;
border-top:1px solid #cccccc;
margin:1em 0;
padding:0;
}
input, select {
vertical-align:middle;
}
/* blog/static/css/style.css */
@charset "UTF-8";
/* --------------------------------
* base
* -------------------------------- */
html {
font-size: 62.5%;
}
body {
color: #333;
font-size: 1.2rem;
font-family: "Hiragino Kaku Gothic ProN", Meiryo, sans-serif;
}
*, *::before, *::after {
box-sizing: border-box;
}
a:link, a:visited, a:hover, a:active {
color: #333;
text-decoration: none;
}
/* --------------------------------
* ヘッダー
* -------------------------------- */
.header {
padding: 30px 4% 10px;
position: fixed;
top: 0;
width: 100%;
background-color: #fff;
display: flex;
align-items: center;
z-index: 10;
}
a.page-title {
font-size: 2rem;
margin: 0;
padding: 0;
color: #888;
}
.main-nav {
list-style: none;
margin: 0;
display: flex;
}
.main-nav li {
margin: 0 0 0 15px;
font-size: 14px;
}
.main-nav a {
color: #888;
}
.main-nav a:hover {
opacity: 0.6;
}
/* --------------------------------
* コンテナ
* -------------------------------- */
.container {
position: relative;
width: 100%;
margin: 0 auto 0;
color: #0d1a3c;
padding-right: 4%;
padding-left: 4%;
}
@media (min-width: 576px) {
.container {
max-width: 540px;
}
}
@media (min-width: 768px) {
.container {
max-width: 760px;
}
}
@media (min-width: 992px) {
.container {
max-width: 960px;
}
}
/* --------------------------------
* 記事一覧
*
-------------------------------- */
.article {
margin-bottom: 6rem;
width: 100%;
}
.created-at {
font-size: 1.4rem;
color: 888;
}
.post-title {
font-size: 2.0rem;
color: #0d1a3c;
line-height: 1.6;
letter-spacing: 1px;
}
ここまでで以下のような見た目になりました。 多少ブログっぽくなったと思います。
次回は記事詳細ページを作っていきます。