0
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Pythonでwebサイトの構築 Part4 ブログサイト完成

Last updated at Posted at 2022-09-22

前回の記事はDBの構築とadminsサイトへのデータ登録を行いました。
今回のきじではいよいよブログサイト編ラストになります。
記事一覧表示から詳細の表示までになります。
今回はまず完成したページから見てみましょう。

完成したページ

記事一覧

url:/localhost:8000/index

image.png

記事詳細

「記事本文」をクリックすると表示されます。url:/localhost:8000/article/該当するpk

image.png
文章についてはネットから適当に拾った文章なのでご了承ください。
それではソースコードを見てみましょう。

投稿一覧ページ

投稿一覧ページのコードは以下のようになります。 ここではPart2(https://qiita.com/Taku_nakahara/items/7dbde3dcd9388aab7d57)で飛ばしていたheader.htmlのaタブ内の構文についても簡単に説明します。

djangoではとすることでurls.pyから該当のviewを呼び出せるためリンクとして使われます。
記事詳細などはDB登録時点でそれぞれプライマリーキーが付与されており、articleテーブルのpk番目とすることで該当記事が呼び出せたりもします。

index.html
{% extends "base.html"%} 
{% load static %}

{% block content%}
<div class = 'container'>
    {% if category %}
        <h3>{{ category }}カテゴリーの記事</h3>
    {% else %}
        <h1>記事一覧</h1>
    {% endif %}
    <div class = 'box-container'>
        {% for article in article_list %}
        <div class = 'box'>
            <div class = 'article'>
                <h5 class = 'article-title'><a href = '{% url 'polls:detail' article.pk %}'>{{ article.title }}</a></h5>
                <br></br>
                <p><a class = 'button' href = '{% url 'polls:detail' article.pk %}'>記事本文を見る</a></p>
                <br>
                <p>{{ article.date }}</p>
                <p><a href = '{% url 'polls:category' article.category %}'>カテゴリー : {{ article.category }}</a></p>
            </div>
        </div>
        {% endfor %}
    </div>

</div>
{% endblock %}
urls.py
from django.urls import path
from . import views

app_name = 'polls'
urlpatterns = [
    path('', views.TopView.as_view(), name = 'top'),
    path('index/', views.IndexView.as_view(), name = 'index'),
    path('category/<str:category>', views.CategoryView.as_view(), name = 'category'),
]
views.py
from django.shortcuts import render, get_object_or_404
from django.http import HttpResponse
from django.views.generic import ListView
from .models import Article, Category

class IndexView(ListView):
    model = Article
    context_object_name = 'article_list'
    template_name = 'index.html'

    def get_queryset(self):
        return Article.objects.order_by('-date')

class CategoryView(ListView):
    template_name = 'index.html'

    def get_queryset(self):
        #category = get_object_or_404(Category, pk = self.kwargs['pk'])
        category = Category.objects.get(name = self.kwargs['category'])
        queryset = Article.objects.order_by('-date').filter(category = category)
        return queryset

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        #context['category'] = get_object_or_404(Category, pk = self.kwargs['pk'])
        context['category'] = self.kwargs['category']
        return context
{{article.title}}について
views.py内のcontext_object_nameで'article_list'を指示しました。これによりArticleテーブル内のデータをすべてarticle_listという名前のリストに格納しています。記事一覧ではそれらを表示するためindex.html内のfor文で一つずつ取り出しています。そしてarticle.titleとすることでtitleを取り出しています。
categoryを表示するには
下記のようにcontext.pyを作成し、category_listに格納することでテンプレート上でforぶんを利用し、取得可能です。今回はヘッダーのカテゴリーのドロップダウン実装時に利用しました。
context.py
from .models import Category

def common(request):
    context = {
        'category_list':Category.objects.all(),
    }
    return context

記事詳細

記事詳細のソースコードは以下になります。
index.html
{% extends 'base.html' %}
{% load static %}
{% block title %}ブログ{% endblock %}
{% block content%}
<div class = 'container'>
    <h2>{{ article.title }}</h2>
    <p>{{ article.date }} / <a href = '{% url 'polls:category' article.category %}'>{{ article.category }}</a></p>
    <p>{{ article.text | safe }}</p>

    <br></br>
    <div class = 'relate-content'>
        <h3>関連記事</h3>
        <br></br>
        {% if article.relate_article.all %}
            <h4>関連記事はこちら</h4>
            {% for re_article in article.relate_article.all %}
            <div class = 'box'>
                <div class = 'article'>
                    <h5><a href = '{% url 'polls:detail' re_article.pk %}'>{{ re_article }}</a></h5>
                    <br></br>
                <p><a class = 'button' href = '{% url 'polls:detail' re_article.pk %}'>記事本文を見る</a></p>
                <br>
                <p>{{ article.date }}</p>
                <p><a href = '{% url 'polls:category' article.category %}'>カテゴリー : {{ article.category }}</a></p>
                </div>
            </div>
            {% endfor %}
        {% else %}
            <h4>関連記事はありません。</h4>
        {% endif %}
</div>

{% endblock %}
urls.py
from django.urls import path
from . import views

app_name = 'polls'
urlpatterns = [
    path('', views.TopView.as_view(), name = 'top'),
    path('index/', views.IndexView.as_view(), name = 'index'),
#追加
    path('article/<int:pk>/', views.ArticleDetail.as_view(), name = 'detail'),
    path('category/<str:category>', views.CategoryView.as_view(), name = 'category'),
]
]
views.py
from django.shortcuts import render, get_object_or_404
from django.http import HttpResponse
from django.views.generic import ListView, TemplateView, DetailView
from .models import Article, Category
# Create your views here.
class TopView(TemplateView):
    template_name = 'top.html'

class IndexView(ListView):
    model = Article
    context_object_name = 'article_list'
    template_name = 'index.html'

    def get_queryset(self):
        return Article.objects.order_by('-date')
#追加
class ArticleDetail(DetailView):
    model = Article
    template_name = 'detail.html'

class CategoryView(ListView):
    template_name = 'index.html'

    def get_queryset(self):
        #category = get_object_or_404(Category, pk = self.kwargs['pk'])
        category = Category.objects.get(name = self.kwargs['category'])
        queryset = Article.objects.order_by('-date').filter(category = category)
        return queryset
関連記事について
detail.html内のarticle.relate_article.allでArticleテーブル内に存在するrelate_articleをすべて取り出し、それがあれば表示するというif文を作成しています。
おまけ
このサイトのようなデザインを作成するCSSは以下です。
style.css
header {
    padding-bottom: 100px;
}

header .navbar-brand {
    margin-left: 50px;
}

.container {
    width: 1000px;
    margin-left: auto;
    margin-right: auto;
}

.container h1 {
    text-align: center;
    margin-bottom:30px;
}

.container h3 {
    text-align: center;
    margin-bottom:30px;
}

.relate-content {
    margin-bottom: 100px;
}

.relate-content h4 {
    text-align: center;
}

.container h5 {
    text-align: left;
}

.box {
    text-align: center;
    float: left;
    width: 300px;
    height: 300px;
    margin: 20px 10px 10px 10px;
    background-color: #fff;
    box-shadow: 0 0 8px rgba(0, 0, 0, 0.16);
    color: #212121;
}

a {
    text-decoration: none;
}

.article {
    display: inline-block;
}

.article {
    text-align: center;
}

.article-title {
    margin-top: 50px;
    margin-bottom: 10px;
}

.button {
    width: 100%;
    display       : inline-block;
    border-radius : 5%;          
    font-size     : 18pt;       
    text-align    : center; 
    cursor        : pointer;    
    padding       : 12px 12px; 
    background    : #000066;   
    color         : white;
    line-height   : 1em;
    transition    : .3s; 
    border        : 2px solid #000066;
  }

  .button:hover {
    box-shadow    : none; 
    color         : #000066; 
    background    : #ffffff;
  }

サイト完成!

完成したサイトは以下のようになります。
トップページ

image.png

投稿一覧

image.png

投稿詳細

image.png

上の関連記事をクリック

image.png

カテゴリーごとでの記事(例Python)

image.png

これで以上になります。質問等ありましたら気軽にコメントください!!
ソースコード全文はGitHubに記載しています。

0
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?