1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

自作クラスの継承&オーバーライドを実用した

Last updated at Posted at 2025-03-30

今回の問題

みなさんこんにちは!
駆け出し前エンジニアのYuyaです。
所々ツッコミポイントがあるかもしれませんが
その場合は質問してくださると今後の学習の糧になりますので、よろしくお願い致します。

今、DjangoでXのクローンアプリを作成しています。
プロフィールページでユーザー情報はそのままで
タブでポスト、リポスト、いいね、コメント
この4つを効率良くコードにする方法を探していました。

スクリーンショット 2025-03-30 21.45.08.png

そもそも継承とは

端的に言うと、継承とはあるクラスが
別に存在しているクラスの性質を受け継いていることです。

一例としては犬があります。
以下がイメージです。
スクリーンショット 2025-03-30 20.46.20.png
(細かい個体差はここでは考えません)
犬種ごとに毛色や大きさが異なりますが、以下の特徴や振る舞いを持っています。

  • 足が四本
  • 嗅覚が人間の約100万倍
  • 嬉しいと尻尾を振る

フォルダ構成

実際の例を見ていきましょう。

以下が今回の大まかなフォルダ構成です。

manage.py
config/
    settings.py
    urls.py
    
apps/
    accounts/
        urls.py
        models.py
        views.py
      
    posts/
        urls.py
        models.py
        views.py
        services.py
      
    profiles/
        urls.py
        views.py
        services.py

画面遷移イメージ

スクリーンショット 2025-03-30 22.09.33.png

とりあえずViewに殴り書き

Serviceクラスが書いてありますが
コメントアウトで概要を記載して詳細は割愛します。

profiles/views.py
from django.contrib.auth.mixins import LoginRequiredMixin
from django.views.generic import TemplateView
from django.shortcuts import get_object_or_404
from apps.accounts.models import CustomUser
from .services import ProfileService
from apps.posts.services import PostService

PROFILE_PAGE = "profile.html"

# ユーザー情報を出力するView
class ProfileView(LoginRequiredMixin, TemplateView):
    template_name = PROFILE_PAGE

    def get_context_data(self, **kwargs):
        # 既存のget_context_dataをコール
        context = super().get_context_data(**kwargs)
        # ログインユーザーを取得
        user = get_object_or_404(CustomUser, id=self.request.user.id)
        # フォロー、フォロワー情報をcontextに渡す
        context['user_relatinships'] = ProfileService.count_following_followers(user)
        return context


# プロフィールユーザーのポスト一覧を出力するView
class PostView(LoginRequiredMixin, TemplateView):
    template_name = PROFILE_PAGE

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        user = get_object_or_404(CustomUser, id=self.request.user.id)
        context['posts'] = PostService.get_my_post_list(user)
        return context

今回の問題で記載がある画像の通り
ProfileView(ユーザー情報)はうまく出力されました。

ただ、ポストタブをクリックした際にユーザー情報が出力されなくなりました。
スクリーンショット 2025-03-30 22.38.34.png

ProfileViewの中でPostViewを呼びたい

困りました。
これだとユーザー情報が出力されません。

ただ、やることは明確になりました。
ProfileViewの中でPostViewを呼び出せば解決しそうだと考えました!!

ここで継承 & オーバーライド

ここでやっと本題の継承が登場です。
完成のコードをみていきましょう!

profiles/views.py
from django.contrib.auth.mixins import LoginRequiredMixin
from django.views.generic import TemplateView
from django.shortcuts import get_object_or_404
from apps.accounts.models import CustomUser
from .services import ProfileService
from apps.posts.services import PostService

class BaseProfileView(LoginRequiredMixin ,TemplateView):
    template_name = "profile.html"
    
    def get_user_activities(self, user):
        """ 子クラスでオーバーライドするためのメソッド """
        return []

    def get_context_data(self, **kwargs):
        # 既存のget_context_dataをコール
        context = super().get_context_data(**kwargs)
        # ログインユーザーを取得
        user = get_object_or_404(CustomUser, id=self.request.user.id)
        # ユーザーのプロフィール情報
        context['user_data'] = ProfileService.format_user(user)
        # ユーザーのフォロー、フォロワー情報
        context['user_relatinships'] = ProfileService.count_following_followers(user)
        # ユーザーの投稿データ
        context['activities'] = self.get_user_activities(user)
        return context


# 継承先の BaseProfileView の get_user_activities をオーバーライド
class PostView(BaseProfileView):
    def get_user_activities(self, user):
        return PostService.get_my_post_list(user)

以下の6ステップで実行されます

  1. PostView.get_context_data() が呼ばれる
  2. BaseProfileView.get_context_data()super().get_context_data() で親の TemplateView.get_context_data() が実行
  3. self.request.user でログインユーザーを取得
  4. context['activities'] = self.get_user_activities(user)PostView.get_user_activities(user) が実行される
  5. PostService.get_my_post_list(user) で投稿データを取得
  6. context を返し、テンプレート (template_name) に渡す

この実行順序でユーザー情報を保ったままタブの切り替えができそうです。

またこの書き方によって、ログインユーザーの取得や
template_nameを複数回書かずに済むといったメリットも享受することができます。

スクリーンショット 2025-03-31 0.58.34.png

これでポスト一覧が出力できました。

これならリポスト、いいね、コメントの一覧もget_user_activitiesをオーバーライドすることで取得してテンプレートで出力できそうです。

最後に

この問題を解決した後に、私は自問自答しました。
いや、お前LoginRequiredMixin ,TemplateViewとか既に継承してんじゃんw

要は継承やオーバーライドで何が行われているかという
基礎の理解はできているが
実用ができていないことが浮き彫りになりました。

この考えをストックしたということに着目して
これからも学習を続けていきます!

1
1
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
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?