Django、ブログ②の記事詳細ページを作る

Python Django

概要

Djangoで、ブログを作るシリーズ②の一つです。記事詳細ページを作っていきます。

ビューの作成

まず、urls.pyに追加します。

path('detail/<int:pk>/', views.NoteDetail.as_view(), name='note_detail'),

そして、詳細ページのビューを作ります。

from django.http import Http404  # 追加

# 略

class NoteDetail(generic.DetailView):
    model = Note

    def get_object(self, queryset=None):
        note = super().get_object()
        if note.is_public or self.request.user.is_authenticated:
            return note
        else:
            raise Http404

get_objectメソッドを上書きして、記事が公開か、又はログインユーザーの場合に表示するようにしました。これで、ログインしていないユーザーは非公開記事が見れません。

テンプレートファイルの作成

note_detail.htmlを作ります。

{% extends 'nblog2/base.html' %}
{% load humanize %}
{% load nblog2 %}

{% block meta_title %}{{ note.title }} | {{ block.super }}{% endblock %}

{% block content %}
    <div id="menu">
        <a href="{% get_return_link request %}">戻る</a>
    </div>

    <article class="container" id="detail">
        <a href="{{ note.thumbnail.url }}" target="_blank">
            <img src="{{ note.thumbnail.url }}" alt="{{ note.title }}">
        </a>
        <div id="detail-container">

            <h1 class="title">{{ note.title }}</h1>

            <div class="meta">
                <p class="category">{{ note.category }}</p>
                <p class="date">{{ note.created_at }}(
                    <time class="updated_at"
                          datetime="{{ note.updated_at | date:'Y-m-d' }}">{{ note.updated_at | naturaltime }}に更新
                    </time>
                    )
                </p>
            </div>


            <div class="text" id="toc-start">
                {{ note.text | markdown_to_html }}
            </div>

        </div>

        <nav id="note-nav">
            <a href="#toc-start">return</a>
        </nav>
    </article>


{% endblock %}

また、note_list.htmlのリンクを修正して、記事詳細ページへ移動できるようにしておきます。11行目のあたり。

<a class="box" href="{% url 'nblog2:note_detail' note.pk %}">

テンプレートフィルタ、タグの作成

今回はマークダウンで記事を書く予定なので、マークダウンテキストをHTMLに変換する必要があります。それをしているのがmarkdown_to_htmlフィルタです。

nblog2.pyに、markdown_to_htmlフィルタを作っておきましょう。

# 追加
from django.conf import settings
from django.utils.safestring import mark_safe
import markdown
from markdown.extensions import Extension

# 略

@register.filter
def markdown_to_html(text):
    """マークダウンをhtmlに変換する。"""
    html = markdown.markdown(text, extensions=settings.MARKDOWN_EXTENSIONS)
    return mark_safe(html)

マークダウンには様々な拡張があり、それらの導入をsettings.pyに定義できるようにしました。とりあえず、settings.pyに次のように追記しておきましょう。

# マークダウンの拡張
MARKDOWN_EXTENSIONS = [
    'markdown.extensions.extra',
    'markdown.extensions.toc',
]

後は、pip install markdownでライブラリをインストールしておけばOKです。これで、記事に書いたマークダウンがHTMLに変換されるようになりました。

もう一つ、<a href="{% get_return_link request %}">戻る</a>の部分にも新しいテンプレートタグがありますね。Django、柔軟な戻るリンクの作成でも説明していますが、これは検索結果の記事一覧から飛んできた場合など、柔軟に前ページへ戻るためのテンプレートタグです。これもnblog2.pyに作っておきましょう。

# 追加
from urllib import parse
from django.shortcuts import resolve_url

# 略

@register.simple_tag
def get_return_link(request):
    top_page = resolve_url('nblog2:note_list')
    referer = request.environ.get('HTTP_REFERER')
    # URL直接入力やお気に入りアクセスのときはリファラがないので、トップぺージに戻す
    if referer:
        # リファラがある場合、前回ページが自分のサイト内であれば、そこに戻す。
        parse_result = parse.urlparse(referer)
        if request.get_host() == parse_result.netloc:
            return referer
    return top_page

CSS

style.cssに、記事詳細ページに関するスタイルを追記しておきます。


/* 詳細 */
#detail-container {
  max-width: 700px;
  margin: 0 auto;
}

#detail h1 {
  margin-top: 100px;
  margin-bottom: 1em;

}

#detail .meta {
  margin-bottom: 100px;
  text-align: left;
}

.text {
  padding-left: 1em;
}

.text > * {
  margin: 1em 0;
}

.toc ul {
  list-style-type: none;
}

.toc::before {
  display: block;
  content: "目次";
  font-weight: 700;
  margin-bottom: 1em;
  margin-left: -1em;
}

#detail h2, #detail h3 {
  margin-top: 100px;
  margin-left: -1em;
}

.text > p {
  line-height: 2;
  text-align: justify;
  text-justify: inter-ideograph;
}

#note-nav {
  position: fixed;
  right: 2em;
  bottom: 2em;
}

#note-nav a {
  font-weight: 700;
  color: #333;
  letter-spacing: 1px;
}

Relation Posts

django-markdownxの紹介

django-markdownを使い、DjangoアプリケーションにMarkdownエディタを導入していくサンプルです。

Python Django Djangoライブラリ Markdown

Comment

記事にコメントする

まだコメントはありません。