【Django(日報アプリ開発)】ListView フィルターのデザイン変更・仕上げ

Django

前回の記事ではユーザー別リストページを表示する方法を解説しました

前回の記事で、当アプリへの機能追加は完了とします

当記事より2記事にわたって、最後の仕上げ「リストビュー」「ユーザー関連のページ」を整え、いよいよデプロイメントへ移っていきたいと思います

当記事では、

  • フィルターを使ったリストビューを整えていく

方法、コードを紹介していきます

最終的にはこんな感じになりました

【リストビュー】

【ユーザー別ページ】

次章よりコピペ可能なコードを紹介していきます

関連書籍

nippo > nippo-top-filter.html

<form method="GET">
<div class="my-3">
    {{ filter.form.date.label }} {{ filter.form.date}}
</div>
{% if username %}
        {% if username == request.user.profile.username %} 
        <div class="my-3">
            {{ filter.form.public }}
        </div>
    {% endif %}
{% endif %} 
    <button type="submit" class="btn btn-primary form-control">ソート</button>
</form>

【変更点】

  1. 公開/未公開フィルターは、ユーザー別ページのみで表示するよう条件分岐を追加
  2. 自身の日報も全体のリストビューでは公開済みのみ表示されます

nippo > models.py

class NippoModelQuerySet(models.QuerySet):
    def search(self, user=None, query=None):
        qs = self.filter(public=True)
        if query is not None:
            or_lookup = (
                Q(title__icontains=query)|
                Q(content__icontains=query)            
            )
            qs = qs.filter(or_lookup).distinct()
        return qs.order_by("-date")

    def get_own(self, user=None, query=None):
        qs = self
        if user.is_authenticated:
            qs = qs.filter(Q(public=True)|Q(user=user))
        else:
            qs = qs.filter(public=True)
        if query is not None:
            or_lookup = (
                Q(title__icontains=query)|
                Q(content__icontains=query)            
            )
            qs = qs.filter(or_lookup).distinct()
        return qs.order_by("-date")

class NippoModelManager(models.Manager):
    def get_queryset(self):
        return NippoModelQuerySet(self.model, using=self._db)

    def search(self, user=None, query=None):
        return self.get_queryset().search(user=user, query=query)

    def get_own(self, user=None, query=None):
        return self.get_queryset().get_own(user=user, query=query)

【変更点】

  1. models.QuerySetとmodels.Managerへ新たなメソッドを追加(get_own)
  2. searchメソッドは今までどおり全体のリストビューで使用し、ユーザー別のページについてはこのget_ownメソッドを使用することにします

nippo > views.py

class NippoListViewByProfile(NippoListView):
    template_name = "nippo/nippo-list-by-profile.html"

    def get_profile(self):
        try:
            username, pk = self.kwargs["obj_slug"].split("-")
        except:
            username = None
            pk = None
        profile_obj = get_object_or_404(Profile, pk=pk)
        return profile_obj

    def get_queryset(self):
        try:
            q = self.request.GET["search"]
        except:
            q = None
        qs =  NippoModel.objects.get_own(user=self.request.user, query=q)
        qs = qs.filter(user__profile=self.get_profile())
        return qs

    def get_context_data(self, **kwargs):
        ctx = super().get_context_data(**kwargs)
        ctx["username"]  = self.get_profile().username

        return ctx

【変更点】

  1. get_querysetメソッドを上書き
  2. models.pyで新たに作成したget_ownメソッドを使ってリスト表示する

nippo > nippo-list.html

{% extends "base.html" %}

{% block content %}
<div class="container d-flex">
    <div style="width:80%;">
    {% block list_block %}
        {% if filter.qs %}
            {% for obj in filter.qs %}
                <div class="card my-3 mx-auto" style="max-width:700px;">
                    <div class="card-header">
                        {{ obj.date|date:"Y年n年j日" }}
                        {% if not obj.public %}
                            <span class="badge bg-secondary">下書き</span>
                        {% endif %}
                    </div>
                    <div class="card-body">
                        <h5 class="card-title">
                        {% if obj.user == request.user %}
                            <a href={% url 'nippo-update' obj.slug %}>
                                {{ obj.title}}<span style="font-size:10px;">(編集)</span>
                        {% else %}
                            <a href={% url 'nippo-detail' obj.slug %}>
                                {{ obj.title}}
                        {% endif %}
                            </a>
                        </h5>
                        <p class="card-text">
                            {{ obj.content }}
                        </p>
                    </div>
                    <div class="card-footer">
                    by 
                    {% if obj.user == request.user %}
                        <span class="badge bg-primary">
                            <a class="text-light" href={{obj.get_profile_view_url}}>あなた</a>
                        </span>
                    {% else %}
                        <span class="badge bg-secondary">
                            <a class="text-light" href={{obj.get_profile_view_url}}>
                                {{ obj.user.profile.username }}
                            </a>
                        </span>
                    {% endif %}
                    </div>
                </div>
            {% endfor %}
        {% endif %}
    {% endblock %}
    </div>
    <div style="width:20%;">
    {% if request.user.is_authenticated %}
        <div class="mt-3 d-flex justify-content-end" style="margin-bottom: 100px;">
            <a href={% url "nippo-create" %} class="btn btn-outline-success float-right form-control">
                新規追加
            </a>
        </div>
    {% endif %}

    {% include 'nippo/nippo-top-filter.html' %}
    </div>     
</div>
{% endblock %}

【変更点】

  1. フィルターの位置を変更(Bootstrapクラスのd-flexを使用)
  2. 次のユーザー別ページで使用するため、ブロックタグ「list_block」を追加
  3. 下書きはすべて非表示

nippo > nippo-list-by-profile.html

{% extends 'nippo/nippo-list.html' %}

{% block list_block %}
    {% if filter.qs %}
    <h2 class="text-center my-3">{{ username }}の日報</h2>
        {% for obj in filter.qs %}
            <div class="card my-3 mx-auto" style="max-width:700px;">
                <div class="card-header">
                    {{ obj.date|date:"Y年n年j日" }}
                    {% if not obj.public %}
                        <span class="badge bg-secondary">下書き</span>
                    {% endif %}
                </div>
                <div class="card-body">
                    <h5 class="card-title">
                    {% if obj.user == request.user %}
                        <a href={% url 'nippo-update' obj.slug %}>
                            {{ obj.title}}<span style="font-size:10px;">(編集)</span>
                    {% else %}
                        <a href={% url 'nippo-detail' obj.slug %}>
                            {{ obj.title}}
                    {% endif %}
                        </a>
                    </h5>
                    <p class="card-text">
                        {{ obj.content }}
                    </p>
                </div>

            </div>
        {% endfor %}
    {% endif %}        
{% endblock %}

【変更点】

  1. 記述を減らすために、nippo-list.htmlをextendsすることに変更
  2. 自分のページでのみ未公開の日報が見れる
  3. 公開/未公開のフィルターの表示

まとめ

全体として変更点をまとめると、

  • フィルターを横並びに表示
  • 下書きの日報を自身のページでのみ表示
  • 公開/未公開のフィルターも自身のページでのみ表示

となります

次回は、ユーザー周りのページ、機能を変更していきます



タイトルとURLをコピーしました