データの受け取り(クラスベースビューから)

データの受け取り

前回は関数ベースのviewからデータを受け取りましたが、今回はクラスベースのviewからデータを受け取る方法に取り組んで行きます。

下準備

sample_app/models.py

from django.db import models

class News(models.Model):

    title = models.CharField(max_length=50, verbose_name='タイトル')
    content = models.TextField(verbose_name='本文')
    created_at = models.DateTimeField(auto_now_add=True, verbose_name='作成日')
    is_public = models.BooleanField(default=False)

sample_app/admin.py

from django.contrib import admin

from .models import News

admin.site.register(News)

sample_app/urls.py

from django.urls import path
from . import views

app_name = 'sample_app'
urlpatterns = [
    path('', views.news_list, name='news_list'),
    path('news/<int:id>', views.news_detail, name='news_detail'),
]

sample_app/views.py

from django.views.generic import ListView, DetailView

from .models import News

class NewsListView(ListView):

    template_name = 'sample_app/news-list.html'
    model = News
    paginate_by = 10

news_list = NewsListView.as_view()


class NewsDetailView(DetailView):

    template_name = 'sample_app/news-detail.html'
    model = News

news_detail = NewsDetailView.as_view()

ターミナル

python manage.py makemigrations
python manage.py migrate
python manage.py createsuperuser
touch templates/sample_app/news-list.html
touch templates/sample_app/news-detail.html

ここまで出来たらadminサイトにログインしてデータを入れましょう。

ターミナル

python manage.py runserver

http://127.0.0.1:8000/adminにアクセスしてスーパーユーザー作成時の情報を入力します。

ログイン後管理画面が開かれているはずです。

sample_appのNewssの追加を押しましょう。
すると作成フォームが表示されるはずです。

適当に記事を3つほど作りましょう。

news-list.html, news-detail.htmlでデータを受け取る

ここからが本題です。

先程views.pyに書いたNewsListViewNewsDetailViewからデータを受け取って表示させましょう。

それぞれnews-list.html, news-detail.html`で受け取り、表示させます。

templates/sample_app/news-list.html

{% extends 'base.html' %}
{% load static %}

{% block main %}
<ul class="list-group">
    <li class="list-group-item active">News</li>
    {% for object in object_list %}
    <li class="list-group-item"><a href="{% url 'sample_app:news_detail' object.pk %}">{{ object.title }}</a></li>
    {% endfor %}
</ul>


{% endblock %}

templates/sample_app/news-detail.html

{% extends 'base.html' %}
{% load static %}

{% block main %}
<h2 class="text-primary">{{ object.title }}</h2>
<p>{{ object.content }}</p>
{% endblock %}

python manage.py runserverしてhttp://127.0.0.1:8000/にアクセスすると、管理サイトで入力した情報が表示されてるかと思います。

NewsListViewからはobject_list, NewsDetailViewからはobjectで情報を取得出来ます。

しかしこれではコードの可読性がいまいちですね。
view.pyでそれぞれのクラスベースビューにcontext_object_nameを指定しましょう。

views.py

from django.views.generic import ListView, DetailView

from .models import News

class NewsListView(ListView):

    template_name = 'sample_app/news-list.html'
    model = News
    paginate_by = 10
    context_object_name = 'newses' # ここ

news_list = NewsListView.as_view()


class NewsDetailView(DetailView):

    template_name = 'sample_app/news-detail.html'
    model = News
    context_object_name = 'news' # ここ

news_detail = NewsDetailView.as_view()

こうすることでobject_listではなくnewsesで、objectではなくnewsで受け取ることが出来ます。

templates/sample_app/news-list.html

{% extends 'base.html' %}
{% load static %}

{% block main %}
<ul class="list-group">
    <li class="list-group-item active">News</li>
    {% for news in newses %}
    <li class="list-group-item"><a href="{% url 'sample_app:news_detail' news.pk %}">{{ news.title }}</a></li>
    {% endfor %}
</ul>
{% endblock %}

templates/sample_app/news-detail.html

{% extends 'base.html' %}
{% load static %}

{% block main %}
<h2 class="text-primary">{{ news.title }}</h2>
<p>{{ news.content }}</p>
{% endblock %}

可読性がさっきよりもよくなりましたね。