- 公開日: 2020年03月09日
Pythonで動くDjango製ブログのご紹介
2019年は 「アフィリエイトはオワコン...」「ブログで稼ぐのは難しい...」 というキーワードをよく目にしました。
しかし、一方で有料コンテンツを配信する note は会員数 2,000万超え、 ホリエモンさんのメルマガも 2万超えの会員数で、 "テキスト" 自体には一定の需要があります。 そこでブログビギナーでも早期に収益を狙える "課金型ブログ" のテンプレートを作成しました。
Python や Django を知らなくても、とりあえず PythonAnywhere や Paizaクラウド などにファイルをコピペし、サーバーを再起動すると Django 製のブログをお楽しみいただけると思います。
尚、デザイン(CSS や JavaScript)についてはほとんど手を付けていませんのでご了承ください。
Django : Python 製の Web フレームワーク。就転職や自分のキャリア実績に活かせるレベルのスキル。
Pythonで動くDjango製ブログのご紹介(コード付き)
とりあえずDjango製ブログサイトを動かしてみる
本稿で紹介するDjango製ブログを動かしている様子
まずは今回ご紹介させて頂きますブログのテンプレートの様子を確認してみましょう。 GitHubから自分のパソコンにプログラムをダウンロードし、 Python ファイルを動かしてみます。
本稿でご紹介するPythonコード: GitHub/oshimamasara
【GitHub のプログラムを動かすコマンド例】
git clone https://github.com/oshimamasara/django_blog.git
cd django_blog
source env/bin/activate
cd mysite
python manage.py runserver
http://localhost:8000/blog にアクセス
投稿画面は http://localhost:8000/admin
//ユーザー名 codecamp、 パスワード pythonlove
(注)上記コマンドは Mac、 Linux 用です。 Windowsの場合は、仮想環境の作成方法等が異なると思います。
WordPress や 無料のブログサービスを利用したことのある方なら、至って普通の内容に思えるでしょう。しかし、 WordPress や ブログサービスを利用するのと違い、このブログのプラットフォームは自分で管理しています。つまり機能の追加やデザインの変更も自分次第。
例えばこのブログのテンプレートを使えば、課金されたら広告を非表示にしたり、特定のコンテンツは有料にしたり、販売数をグラフで出力したり、 SNS機能を付けて note みたいにユーザー投稿型にしたり、といろいろなことができるようになります。 また Python といえばデータ分析が得意ですので、ちょっと頑張れば AI による "おすすめ機能" も不可能ではないでしょう。
しかし機能を拡張しようと思うと、やはり基本的な構成を理解しておかなければなりません。 Python や Django の基礎はあるとした上で、今回実装した内容についてご紹介していきます。
【今回ご紹介するブログの主な機能】
- 文字列を使うURLの設定
- エディタ機能(マークダウン)
- ファイルのアップロード
- サイトマップ
- base.html の作成・設定方法
- JS や CSS などを管理する static の設定
【余談 Djangoとブログ】
"ブログ"といえば WordPress に代表されるように CMS を使った運用が一般的です。
Python にも djangoCSM や Mezzanine のような CSM はありますが、 Python 初心者にとっては恐らく使いにくいと思います。
理由は、 "構造" "仕組み" が分かりにくいから。
様々な機能があるのはいいのですが、動きの意味を理解しておかないと "カスタマイズ" はほぼ無理です。
少し学習時間は必要かもしれませんが、自分で "ブログのテンプレート" を作っておくと、幅広く応用できると思いますよ。
また自身のポートフォリオとしても活用できるでしょう。
Djangoの基礎を復習
このセクションのコード: GitHub/oshimamasara
MVT的な動きをする Djangoは、 2〜3日コードを触らなかっただけで忘れてしまいますよね。 少し復習を兼ねて Django のブログアプリを起動してみます。
まずは Python 3.6 以上の仮想環境を作成し、 Django をインストール。
【Mac, Linux】
python3.7 -m venv env
source env/bin/activate
pip install django
【Windows】
python3.7 -m venv env
env\Scripts\activate
pip install django
そして startproject & startapp を実行。
【Mac, Linux】
django-admin startproject mysite
cd mysite
python manage.py startapp blog
【Windows】
django-admin.exe startproject mysite
cd mysite
python manage.py startapp blog
きちんとプロジェクトと App がセットされたかどうかは、 python manage.py runserver
してみるとわかりますね。上図の上側のように localhost:8000 にアクセスして Django のロケット画面が写っていれば OK。コマンドを終了する際は Ctrl + C で閉じましょう。
Django の MVT の感覚を思い出すために、上図のように少し簡単なプログラムを実行。 http://localhost:8000/about にアクセスしたら、簡単な文字を出力できるように Django をセットしたいと思います。
【編集するファイル】
- settings.py
- mysite/urls.py
- blog/urls.py
- blog/viws.py
settings.py の INSTALLED_APPS に 'blog' を追加し(上図①)、 mysite/urls.py に blogアプリの blog/urls.py を許可(上図②)。そして blog/urls.py に http://localhost:8000/about の 'about' を追加し(上図③)、 blog/views.py で出力を制御(上図④)。 この状態で python manage.py runserver
し、 http://localhost:8000/about にアクセスすると以下のようになります。
ちょっと urls.py や views.py を触ると Django の感覚が蘇ってきますよね。 次はブログ記事を管理するためのデータベースを作成してみます。
Django/ブログのデータベースを作成する方法
このセクションのコード: GitHub/oshimamasara
Djangoには Flask や Bottle と違って、デフォルトで SQLite のデータベースがセットされていますね。こちらのデータベースにブログ用のテーブルを作成していきます。
【今回用意するブログ記事の項目】
- タイトル
- URL
- 本文
- 作成日
- 更新日
【編集するファイル】
- blog/models.py
- blog/admin.py
Djangoのデータベース操作は、 blog/models.py の編集で OK。 上図の models.py のように各項目をセットし、データベースのセット内容が表示されるように管理画面を制御する admin.py を上図のように編集します。
ネットなどでよく見る Django のチュートリアルでは、 URL の部分を ID で管理していると思います。
しかし、 SEOに強いサイトの多くは、 URL は番号ではなくて "文字"。
今回は作成したブログのテンプレートを少しでも実用的に使えるように、 URL を "文字" で制御するように設定します。
slug を編集することで URL のパラメーターを変えられます。
尚、今回は "文字のURL" に SlugField() を使っていますが、他には URLField() もあります。
上図のプログラムの状態を実行し、 http://localhost:8000/admin にアクセスすると、ログイン画面が登場。 GitHub のプログラムをクローンされている方は user name: codecamp , password: pythonlove でログインできます。 Git Clone されていない方は、以下のコマンドでユーザーを作成し、ログインを実行。
python manage.py createsuperuser
Django の管理画面にログインすると、下記のように "Posts" という項目が登場します。
http://localhost:8000/admin にログインした状態
Posts をクリックすると、ブログを投稿できますので、適当に入力。そして URL にアクセスしてみるも ❌ です(下図参照)。
これはデータベースには新しく URL や文字が追加されましたが、 Django の方でデータベースに記録した URL(slug) へのアクセスを許可していないので、データベース内のテキストの呼び出しも正しく行われていないため。下記のように 3つのファイルを編集します。
Django/ブログのURLを文字列にする方法
【編集するファイル】
- blog/urls.py
- blog/views.py
- blog/templates/blog/detail.html
まずブログ記事を作成する時にセットする slug(URLのパラメーター) を blog/urls.py にセット。 6行目の
path('<slug:slug>/', views.post_detail,・・・)
が新しく足されたわけですが、 <slug:slug>
の部分がわかりにくいですよね。左側がデータ型を表して、右側が views.py へ渡すデータになります。例えばブログ記事を作るときに、
として slug を sample1 として記事を保存すれば、 http://localhost:8000/smaple1 にアクセスした時、 blog/views.py に sample1 が 変数 slug として渡されます。
slug のワークフロー
そして上図の views.py を見ていくと、 9行目のところでデータベースにアクセスした sample1 があるかどうか get_object_or_404() でデータチェックし、 smaple1 があればそのデータベースの内容を detail.html に反映。
detail.html の方は、 blog/views.py から引き継いだ "post" のデータを使い、 タイトルや本文を post.title 、 post.text で出力。 "title" や "text" はデータベースの設定ファイル blog/models.py の内容と同じになりますね。
あらためてブログ作成の時の slug の URL にアクセスすると、以下のように記載内容を出力できました。
しかし、ブログの編集画面が "テキスト形式" なので改行もなく、味気ないですよね。ブログの編集画面を "HTML" か "マークダウン" のどちらかにすれば文字レイアウトを制御できますので、今回は比較的簡単なマークダウンの方でセットします。
Django/マークダウン機能を追加する方法(MarkdownX)
このセクションのコード: GitHub/oshimamasara
Djangoのマークダウンパッケージ・リスト(リンク)
Djangoでマークダウンを使おうと考えた時、頼りになるのが Django用のパッケージ。 マークダウンについては上図のように 8種類ほどありますが、今回は GitHub で一番人気の MarkdownX を使ってみることにしました。
Django 用のパッケージ: MarkdownX を Django のプロジェクト内で使おうと思うと、以下のコマンドが必要。
pip install django-markdownx
公式ドキュメント*にも MarkdownX を Django に実装する手順が紹介されていますが、 内容が Djangoバージョン 1 のモノで、どこか怪しいような... 私の場合は、公式ドキュメント通り進めた結果 ❌ でした。
StackOverflow や YouTube などでいろいろ調べた結果、以下のような感じで MarkdownX を実装完了。
ちょっとややこしすぎますよね。整理して MarkdownX を実装した手順をご紹介していきます。
【編集したファイル】
- settings.py
- mysite/urls.py
- blog/models.py
- blog/admin.py
- blog/templates/blog/detail.html
まず上図①の settings.py 41行目では、 MarkdownX 自体を Djangoプロジェクト内で使用することを宣言。そして②では settings.py の最終行に STATIC と MEDIA に関するコードを追加。
STATIC ・・・ CSS や JavaScript など静的なファイルを保存する場所
MEDIA ・・・ アップロード・ファイルなどを保存する場所
STATIC については、 MarkdownX を動かすために必要な CSS や JavaScriptファイルを格納するための準備で、 MEDIA については画像のアップロード先。 MarkdownX を採用すると、ブログ編集画面で画像をドラッグ&ドロップするだけでアップできます。
そして③は、 MarkdownX の機能を管理画面などでも有効化するための設定で、 ④で model の変更。 models.py のポイントとしては、 11行目の
text = MarkdownField()
textフィールドの設定をマークダウン形式に変更することで、 マークダウンが有効に。
⑤は管理画面で MarkdownX の機能を有効化するものですが、 11行目の部分で元のコードを MarkdownX のクラスに変更しています。これによって以下のようになります。
MarkdownX採用 前 の管理画面 | MarkdownX採用 後 の管理画面 |
せっかく分かりやすいように slug や 記事作成日 をセットしていたのに、 MarkdownX のせいで管理画面が変わります。 " from markdownx.admin import MarkdownxModelAdmin
" にもたくさんの機能があると思いますが、ドキュメントが少ないこともあり、使いにくいようであれば 11行目は "なし" でもそれほど差し支えはないでしょう。 11行目なしでも、マークダウン機能や画像アップロード機能は使えます。
そして最終的に ⑥ のように、マークダウンのデータを出力するところのコードを変更。 safe については、「安全なコードなので、エスケープしないでね」 という意味です。 Django は標準で HTMLコードをエスケープする仕様になっているため、この "safe" がないと HTMLタグを有効化できない仕組みになっています。
詳しくは調べられていませんが、 post.text を post.formatted_markdown|safe に変えているのに、 formatted_markdown = text で制御できるのは、今回ブログの本文だけをマークダウンにしたからです。
例えば SNS 系の Webアプリを考えると、本文以外にもデータベースの情報をピックアップしたい場面も考えられるでしょう。
そうなると formatted_markdown = text では上手くいかないような...
今回は "とりあえず" の部分もありましたので MarkdownX を使ってみましたが、場合によっては ckeditor などの HTMLエディタの方がいいかもしれません。
さて MarkdownX の設定が整ったところで、上図のようなコマンドを実行。 一番上の
python manage.py collectstatic
では、 MarkdownX を管理画面等で使うために必要な JavaScript ファイルや CSS ファイルを staticフォルダにセット。コマンドを実行すると、下図のように自動的に必要なファイル群がセットされます。
そしてデータベースの内容変更を makemigrations
と migrate
で処理して、 runserver
すると、管理画面の様子が変わっています。
http://localhost:8000/admin にアクセスし、新規投稿画面を開いて text 欄にマークダウンを入力すると、 <h2>
や HTMLコードが有効になっていることが確認できます。また画像はドラッグ&ドロップで自動的にセットでき、画像サイズは 500×250 にリサイズ処理。あとは CSS で画像サイズを調整すれば OK といった感じです。
そしてマークダウン形式で編集した投稿内容を、ブラウザ画面で確認すると、上図のようにきちんと HTML 形式で出力されている事が確認できますね。
この際 <script>
もエスケープされることなく有効に。ちょっと記事別で JavaScript を利用したい時には便利そうな環境といえるでしょう。
さてここまで進めてきましたが、実はこのブログサイトのトップページ、まだありません。 index.html を作って、ブログサイトらしく整えていきましょう。
Django/ブログのトップ画面の作り方
このセクションのコード: GitHub/oshimamasara
http://localhost:8000 にアクセスした結果の画像
ブログのトップ画面にはいろいろなレイアウトがあると思いますが、今回は上図のようにシンプルなモノにしてみました。このトップ画面は、以下の様なファイル編集で実現しています。
【編集したファイル】
- blog/urls.py
- blog/views.py
- blog/templates/blog/index.html
Djangoの公式チュートリアル*を経験済であればなんてないコードで、①から順に辿って確認するとデータの流れが把握できると思います。
③の 15行目では、記事の URL 部分で "名前空間" が使用されて、 URL を動的に制御。
とりあえずはこれでトップページを表示できますが、実際には CSS や JavaScript を読みこんだりしてもっと複雑になります。例えば以下のような点が必要になってくるでしょう。
- CSSファイル や JavaScriptファイルを読み込める環境
- base.html の設定
- sitemap.xml の設定
とりあえず SEO 的に必要な sitemap.xml から確認していきましょう。
Django/sitemap.xmlの作り方
このセクションのコード: GitHub/oshimamasara
WordPressなどを使用していれば全く気にすることのない sitemap.xml ですが、フレームワークを使用する場合、自分で sitemap.xml を準備する必要があります。
【編集するファイル】
- settings.py
- blog/models.py
- mysite/urls.py
Djangoの場合は、標準で sitemap 機能が用意されていますので、下図①のように settings.py にコードを追加。
'django.contrib.sitemaps',
'django.contrib.sites',
SITE_ID = 1
sitmap を利用する際は、上記のように sitemap ライブラリを追加する以外に SITE_ID をセットする必要があります。
そして sitemap とデータを共有するために、 models.py を編集(上図②部分)。 get_absolute_url()
はイメージしにくい関数ですが、要は URL のチェック機能、 slug の URL が存在するかをチェック(公式doc)。そしてその URL のチェック先は、 return reverse()
で決められており、 "名前空間" を使った URL 制御。 reverse()
関数の中に 'post:post_detail'
とありますが、 これは blog/urls.py の情報とリンクしています。 'post:post_detail'
の post
は app_name='post' とリンクし(上図②の赤線部分)、 'post:post_detail'
の post_detail
は name='post_detail'
とリンク(上図②のオレンジ線部分)。
そして name='post_detail'
にアクセスする際には slug の情報が必要となるため、reverse()
関数の中に slug を引数としてセット(②部分)。ここの処理は一から作成していくのは難しく、上図②部分をテンプレ的に使用する方法が無難でしょう。
最後に http://localhost:8000/sitemap.xml にアクセスされた時の出力制御が必要で、それは mysite/urls.py に記載。 sitemap.xml の出力結果は、 25行目から 30行目部分で定められており、 Django の sitemapライブラリにある GenericSitemapクラスを使用しています。 GenericSitemapクラスでは、以下の項目が設定可能。
- URL(queryset)
- 日付(date_field)
- 優先度(priority)
27行目の 'queryset': Post.objects.all(),
部分をコメントアウトしている理由は、 sitemap.xml で表示された時の順番を新しい物順位するため。 24行目の部分で一旦データベースをソートすることで、 sitemap.xml に表示される順番が新しい物順になります。
sitemapの準備ができたら、 model.py の変更内容を反映させるために以下のコマンドを実行。
python manage.py makemigrations
python manage.py migrate
そして runserver し、 http:localhost:8000/sitemap.xml にアクセスすると、本セクション冒頭に紹介したような sitemapページが表示されると思います。
ここまでで テキストスタイルのURL、 sitemap、 マークダウン形式 と SEO が施されたブログサイトができました。ここで一旦終了しても OK と思いますが、今後 index.html 、 detail.html 以外に カテゴリー用 のページや問い合わせページなど "ページ" が増えてくると、 HTML の管理が煩雑に。
こうしたテンプレートの問題は、 base.html を利用すると解決できます。
Django/base.htmlの設定方法
このセクションのコード: GitHub/oshimamasara
Djangoでは {% if ・・・・
や {% for・・・
のような HTML内に組み込めるテンプレートや専用タグがあり、その中に {% extends ・・・・}
というテンプレートの連絡機能があります。この {% extends ・・・・}
を使うことで、 index.html や detail.html などの HTMLファイルの管理が簡単に。
【編集するファイル】
- blog/templates/blog/base.html
- blog/templates/blog/index.html
- blog/templates/blog/detail.html
{% extends ・・・・}
を使う実際の様子としては、上図のように、従来 1つの HTMLファイルで制御していた内容を 2つの HTMLファイルに分割。 上図は index.html に {% extends ・・・・}
を採用したモデルで、 index.html 以外でも使う部分の HTMLコードを base.html に、 index.html でしか使わない HTMLコードを index.html に記録。
- index.html以外でも使うコード : base.html
- index.htmlのみで使うコード : index.html
結果的には index.html 一つがブラウザによって読み込まれるわけですが、 "共通部分" と "専用部分" を分けて管理すると、 Googleアナリティクス や API キー等サイト全体に関するコードが変わった時も、 base.html だけを変更すれば OK という管理しやすい仕組みに。
base.html と index.html の 2つの HTMLコードの連絡は、 {% block title %}
や {% block content %}
を目印に連絡し合い、 各項目の最後に {% endblock %}
とすることで連絡終了を意味します。
そして実際の http://localhost:8000/index.html は、下記のような形で、 base.html + index.html の結果が出力されます。
この Django の {% extends ・・・・}
を使った base.html、最初は難しく感じるかもしれませんが慣れてくると非常に便利です。 index.html 以外の detail.html についても、以下のように base.html 式に変更してみました。
detail.html に base.html を採用した様子
先ほどの index.html とほぼ同じ内容で、 {% block %}
を使用。ちなみに {% block
の後の title
や content
というキーワードは任意の文字です。 base.html と連携するために必要なキーワードになりますので、特別 content
である必要はなく {% block post_text %}
や {% block thunmbnail_image %}
などでも OK。
そして base.htmlを採用した detail.html の出力結果は以下の通り。
<title>
部分と <body>
部分を上手く連絡しあい、記事毎の個別内容が出力できている様子が確認できます。
これで base.html はセット完了です。あとは CSS や JavaScriptをファイル形式で読み込めるようにセット。
Django/staticでCSSファイルやJavaScriptファイルを管理する方法
このセクションのコード: GitHub/oshimamasara
Web制作の基本ともいえる CSS や JavaScript をファイル形式で読み込む方法、 Djangoでは "static" というフォルダを作成して、そこで CSS ファイルや JavaScript ファイルを保存・管理します。
【編集するファイル】
- blog/templates/blog/base.html
- blog/static/css/blog.css
- blog/static/js/blog.js
"static" 、 実は今回がはじめての登場ではなく MarkdownX の設定時でも登場しています。いくつかのチュートリアルを確認すると、プロジェクトと同じディレクトリレベルで static フォルダを作成するケースもあれば、 アプリレベルでstaticフォルダを作成するケースも。
今回のケースでは、一度 MarkdownX でプロジェクトレベルの staticフォルダを作成していますので、 アプリレベルのディレクトリに staticフォルダを作成し、そこに CSS や JS フォルダを作る方が簡単と判断しました。以下のようにアプリレベルのディレクトリに "static" フォルダを作成し、 staticフォルダ内に css と js フォルダを作成します。
フォルダとファイルの準備ができたら、あとはそのファイルを読み込んでもらうための処理が必要になります。 base.html のトップに
{% load static %}
と一行加えることで、先ほど作成した アプリレベルの staticフォルダを読み込んでくれます。そして CSS と JavaScript ファイルを HTMLで読み込むために上図 base.html の 6行目、 7行目のように HTMLコードを追加。
<link rel="stylesheet" href="{% static 'css/blog.css' %}">
<script type="text/javascript" src="{% static 'js/blog.js' %}"></script>
そしてブラウザ側の結果を確認すると、 下図に示すように CSSファイルと JavaScriptファイルが読み込まれて、レイアウトと機能が有効になっていることが確認できますね。
あとは Bootstrap を採用したい場合は、 cssフォルダと jsフォルダに Bootstrap専用のファイルを保存し、 base.html で読み込み。 jQueryを利用したい場合であれば、 jsフォルダに専用ファイルを保存、など WordPress では実現しにくかったデザイン要素も自由に取り入れられます。
また "static" というフォルダ名、 {% load static %}
という static の読み込みで実行していますが、 "graph" や "chart" など個別の機能毎にファイルを管理してもいいかもしれません。
\AIエンジニアに必要なスキルが身に付く/
まとめ
今回 Django でブログ、ということで以下の内容まで実装しました。
・ 文字列を使うURLの設定
・ エディタ機能(マークダウン)
・ ファイルのアップロード
・ サイトマップ
・ JS や CSS などを管理する static の設定
実際にはこの他にも "検索機能" や "カテゴリー機能"、 "タグ機能" なども必要かもしれません。パーソナルレベルのブログを Django で立ち上げるのはそれなりのモチベーションと時間が必要ですが、 ポートフォリオにおいて有効な制作物になりますし、 Djangoベースのサイトを元に、noteのような "課金型ブログ" や "自サイトでの物販" など 様々な Webサービスの展開も可能です。
Pythonの基礎が完了した上でお時間のある方は Django 挑戦する価値があるでしょうし、 Python 基礎がまだの方は、まずは頑張って基礎をマスターしちゃいましょう。
「Pythonの本や学習サイトで勉強してみたけれど、いまいち身についてる感じがしない・・・」 「Pythonの辞書型難しすぎる・・・」 なんてつまずいてしまったら、CodeCamp の Pythonコースでチャチャッと基礎をクリアしませんか?
CodeCamp Pythonコース 148,000円(入学金別途30,000)
「シンプルに高い!」 「それだけ受講料払って、元取れるの???」 などなど、いろいろなご意見はあると思います。でも今のまま、つまずいたまま立ち止まっていては何も変わりません。
『難なくプログラミングをこなすカッコイイ自分』を一度は想像したことがありますよね? 今年こそ、そんな自分を実現させましょう!
CodeCampでの受講の中でもつまずくことはあるかもしれませんが、200名以上の最強講師陣があなたのプログラミング学習を徹底サポートし、スキル習得へと確実に導いてくれます。 レッスン内容と受講料が見合うのかご心配でしたらまずは "無料体験" から始められてはいかがでしょう?
無料のレッスンだからと言って簡易的なものではありません。講師しっかりとCodeCampの価値を感じていただけるはずです!
昨今のプログラミング・ニーズの高まりを受けて、無料体験枠が埋まっている日もあります。予め、ご了承ください。
- この記事を書いた人
- オシママサラ