豆腐とコンソメ

豆腐とコンソメ

もろもろのプログラム勉強記録

Djangoを学ぶ(4):リンクをはる

前回の続き

tohutokonsome.hatenablog.com

今回は、以下のようにトップ画面から個別記事に飛ぶようにリンクを貼っていきます。

f:id:konoemario:20170613232718p:plain:w500

個別記事を返す関数をviews.pyに追加する。

まず、前回のhome.htmlを返すhome関数と同様に、個別記事を返す「post_details」関数を作成します。
ポイントは、Postオブジェクトの取得方法です。

views.pyを抜粋

from django.shortcuts import render
from .models import Post

def post_details(request, post_id):

    post = Post(pk=post_id)

    return render(request,'posts/post_details.html', {'post':post})

前回のhome.htmlでは、トップ画面に記事一覧を表示するために、Postオブジェクトをすべて取得していました。

  #Postオブジェクトを取得
    posts =  Post.objects.order_by('pub_date')

ですが、今回必要なのは、個別記事に表示するひとつのPostオブジェクトのみ必要になります。
ここでは、特定のPostオブジェクトを取得するための方法として、

 post = Post(pk=post_id)

という書き方をしています。

※参考
クエリを生成する — Django 1.4 documentation

pkは字のごとくプライマリキーを表しており、管理者画面から投稿した記事にはデフォルトでidなるプライマリキーが振られています。
ここでは、引数から与えられたpost_idをもとに、一意のPostオブジェクトを取得しています。
取得したPostオブジェクトは、「post_details.html」に渡します。

次に、post_details関数を呼び出すための定義をurls.pyに追加します。


urls.pyの編集

urls.pyを抜粋

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    #home
    url(r'^$',posts.views.home, name='home'),
    #detail
    url(r'^posts/(?P<post_id>[0-9]+)/$',posts.views.post_details, name="post_detail"),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

ちょっとわかりずらいのですが、「P<post_id>」の部分がポイントなのかなぁと思っています。
Djangoは、「http://localhost/posts/[0-9]+」にマッチするリクエストがあった場合に、さきほど作成した「post_details」関数を呼び出します。
このとき、「P<引数名>」書いておくと、Djangoは、post_details関数に名前付き引数として、引数を渡すみたいです。

これによって、前述のpost_details関数は、受け取ったpost_idをキーに、Postオブジェクトを取得することができます。

ちなみに、「P<post_id>」と書かないと、関数に引数を渡さないような印象を受けますが、特に書かなくても正規表現でキャプチャした値は、関数に渡す仕組みになっているようです。
ただ、「P<post_id>」としておくと、名前付き引数として扱えるので、引数の順番を意識する必要がなくなるというわけです。

※参考
URL ディスパッチャ — Django 1.4 documentation


home.htmlの編集

home.htmlでは、記事のタイトルにタグをつけて、記事へのリンクを貼ることにします。

home.htmlより抜粋

<!-- postオブジェクトは複数あるので、こんな感じでループさせる。-->
{% for post in posts.all %}
     <h1>{{ post.title }}</h1>
    <p> {{ post.pub_date }}</p>
    <img src="{{url 'post_dettail' post.id}}" style="max-height:300px"/>
    <p> {{ post.body }} </p>

{% endfor %}

「{{url ‘urls.pyに定義したname’}}」は前回同様なのですが、post.idをここに書くことで、引数として渡せるみたいです。


post_detail.htmlの作成

最後に、個別記事のhtmlを作成します。
といっても、ほぼhome.htmlをコピペしただけの内容になっています。

post_detail.htmlの抜粋

    <a href="{% url 'post_detail' post.id %}"><h1>{{ post.title }}</h1></a>
    <p> {{ post.pub_date }}</p>
    <img src="{{post.image.url}}" style="max-height:300px"/>
    <p> {{ post.body }} </p>

次回はしばらくないかも

とりえず、ここまでの内容でトップ画面から個別記事に遷移するブログちっくな機能の実装ができました。

画面のレイアウトについては、cssの話になってしまうので、メモが必要な局面がでてきたら更新していこうかと思います。