複数ページの重複モデルを整理して保守性・拡張性を上げる

投稿日:2025年10月07日

はじめに

最近、自分の Django アプリ(KakuhanApp)で複数ページに似たようなコメント機能を実装していたら、修正や機能追加のたびに複数ファイルを直す必要があって面倒になってきました。
そこで「共通部分を抽象化して core アプリにまとめる」リファクタリングを行うことで、今後の拡張や修正を楽にしたいと考えました。この記事はその手順やポイントをまとめたものです。


1. 最初の状態

  • 複数のアプリ(ブログ、掲示板、相性表など)で、ほぼ同じ Comment / Reply モデルを重複定義していた。

  • 各モデルに name, text, created_at, image, video のような同一フィールドが散らばっており、仕様変更時に複数箇所直す必要があった。

  • 追加機能を実装したいときも、すべてのモデルにフィールドを追加する作業が面倒。

2. 改善の方針

  • 共通フィールド(name, text, created_at, image, video)を coreBaseComment / BaseReply として抽象化(abstract = True)。

  • 各アプリ側のモデルはその Base を継承し、固有の外部キー(例:blog / topic / character)や掲示板固有フィールドだけを宣言する。

  • テンプレート(コメント一覧の HTML)は既存のものを変更せず使えるように配慮する(comment.replies.all などを維持)。

3. 実際の修正

3-1. 元の重複モデル

class BlogComment(models.Model): # ブログ用モデル
    blog = models.ForeignKey(BlogPost, on_delete=models.CASCADE, related_name="comments") 
    name = models.CharField(max_length=100, default="匿名")   
    text = models.TextField()   
    created_at = models.DateTimeField(auto_now_add=True)

    def __str__(self):   return f"{self.name}: {self.text[:20]}" 

class ForumComment(models.Model): # 雑談掲示板用モデル
    topic = models.ForeignKey(Topic, related_name="comments", on_delete=models.CASCADE)
    name = models.CharField(max_length=100, default="匿名")
    text = models.TextField()
    image = models.ImageField(upload_to="forum_comments/images/", blank=True, null=True)
    created_at = models.DateTimeField(auto_now_add=True)

    def __str__(self):   return f"{self.name}: {self.text[:20]}" 

このように似た項目がファイルごとに散らばっていました。

 

3-2. 作った共通基底(core/models/base_comment.py

class BaseComment(models.Model): 
    name = models.CharField(max_length=100, default="匿名") 
    text = models.TextField() 
    image = models.ImageField(upload_to="comments/images/", blank=True, null=True) 
    video = models.FileField(upload_to="comments/videos/", blank=True, null=True) 
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta: 
        abstract = True 

    def __str__(self):
        return f"{self.name}: {self.text[:20]}" 

ポイント

  • abstract = True にしているので core 自体にテーブルは作られない。

 

3-3. 各アプリ側の子モデルへ継承

class BlogComment(BaseComment): # ブログ用モデル
    blog = models.ForeignKey(BlogPost, on_delete=models.CASCADE, related_name="comments") 

class Comment(BaseComment): # 雑談掲示板用モデル
    topic = models.ForeignKey(Topic, related_name="comments", on_delete=models.CASCADE) 
    image = models.ImageField(upload_to="forum_comments/images/", blank=True, null=True) 

 

ポイント

  • 子モデルで image/video を再定義することで、以前と同じ upload_to を保持できる(既存メディアのパスを変えたくないとき)。

4. 基底クラスにまとめて得たメリット

基底クラス(抽象クラス)を導入したことで得られた具体的なメリットを挙げます。

  • 機能追加や修正が1箇所で済む
    例えば「コメントにいいね機能を追加したい」といった変更も、BaseComment(基底クラス)にフラグフィールドや表示用メソッドを追加するだけで対応できます。これにより、各アプリのコメントモデルを個別に修正する必要がなくなります。

  • コード重複が減る
    各コメントモデルで同じフィールド定義を繰り返す必要がなくなり、共通部分はすべて抽象クラスに集約できます。結果として、コードがより簡潔で保守しやすくなりました。

  • 新たなページへの追加が容易
    新しいページにコメント機能を追加する際も、BaseComment を継承するだけで済むため、開発コストを大幅に削減できます。

このように、「基底クラス(抽象クラス)」を導入することで、Djangoアプリ全体の保守性・拡張性・再利用性が格段に向上しました。

おわりに

今回は「まずは共通化して土台を固める」ことにフォーカスしました。これで次のステップ(機能追加や修正)は、ぐっと簡単になります。

重複を見つけたら一度 abstract ベースにまとめてみることを強くお勧めします 。


記事一覧に戻る

関連記事

Bootstrapでトーストを使う方法 ― ポップアップ通知の実装 プログラミング
Bootstrapでトーストを使う方法 ― ポップアップ通知の実装
テンプレートで「〜前」の形式で表示する方法 — Django の timesince を日本語化する プログラミング
テンプレートで「〜前」の形式で表示する方法 — Django の timesince を日本語化する
文章の行数をCSS(-webkit-line-clamp / line-clamp)で制限して見た目を整えた プログラミング
文章の行数をCSS(-webkit-line-clamp / line-clamp)で制限して見た目を整えた
X(旧Twitter)カードを正しく表示するためのHTMLの書き方 プログラミング
X(旧Twitter)カードを正しく表示するためのHTMLの書き方
VScodeでPython、HTML/CSSコードを自動で整形する方法 プログラミング
VScodeでPython、HTML/CSSコードを自動で整形する方法

人気記事

はじめまして None
はじめまして
閲覧数: 872
プログラミング初心者が独学で1からPythonを学習し、資格取得・webアプリ作成まで。(資格取得編) プログラミング
プログラミング初心者が独学で1からPythonを学習し、資格取得・webアプリ作成まで。(資格取得編)
閲覧数: 848
VScodeでPython、HTML/CSSコードを自動で整形する方法 プログラミング
VScodeでPython、HTML/CSSコードを自動で整形する方法
閲覧数: 253
X(旧Twitter)カードを正しく表示するためのHTMLの書き方 プログラミング
X(旧Twitter)カードを正しく表示するためのHTMLの書き方
閲覧数: 67
文章の行数をCSS(-webkit-line-clamp / line-clamp)で制限して見た目を整えた プログラミング
文章の行数をCSS(-webkit-line-clamp / line-clamp)で制限して見た目を整えた
閲覧数: 39

おすすめ記事

プログラミング初心者が独学で1からPythonを学習し、資格取得・webアプリ作成まで。(資格取得編) プログラミング
プログラミング初心者が独学で1からPythonを学習し、資格取得・webアプリ作成まで。(資格取得編)
VScodeでPython、HTML/CSSコードを自動で整形する方法 プログラミング
VScodeでPython、HTML/CSSコードを自動で整形する方法

記事へコメントする

コメント一覧(0件)

関連記事

Bootstrapでトーストを使う方法 ― ポップアップ通知の実装 プログラミング
Bootstrapでトーストを使う方法 ― ポップアップ通知の実装
テンプレートで「〜前」の形式で表示する方法 — Django の timesince を日本語化する プログラミング
テンプレートで「〜前」の形式で表示する方法 — Django の timesince を日本語化する
文章の行数をCSS(-webkit-line-clamp / line-clamp)で制限して見た目を整えた プログラミング
文章の行数をCSS(-webkit-line-clamp / line-clamp)で制限して見た目を整えた
X(旧Twitter)カードを正しく表示するためのHTMLの書き方 プログラミング
X(旧Twitter)カードを正しく表示するためのHTMLの書き方
VScodeでPython、HTML/CSSコードを自動で整形する方法 プログラミング
VScodeでPython、HTML/CSSコードを自動で整形する方法

人気記事

はじめまして None
はじめまして
閲覧数: 872
プログラミング初心者が独学で1からPythonを学習し、資格取得・webアプリ作成まで。(資格取得編) プログラミング
プログラミング初心者が独学で1からPythonを学習し、資格取得・webアプリ作成まで。(資格取得編)
閲覧数: 848
VScodeでPython、HTML/CSSコードを自動で整形する方法 プログラミング
VScodeでPython、HTML/CSSコードを自動で整形する方法
閲覧数: 253
X(旧Twitter)カードを正しく表示するためのHTMLの書き方 プログラミング
X(旧Twitter)カードを正しく表示するためのHTMLの書き方
閲覧数: 67
文章の行数をCSS(-webkit-line-clamp / line-clamp)で制限して見た目を整えた プログラミング
文章の行数をCSS(-webkit-line-clamp / line-clamp)で制限して見た目を整えた
閲覧数: 39

おすすめ記事

プログラミング初心者が独学で1からPythonを学習し、資格取得・webアプリ作成まで。(資格取得編) プログラミング
プログラミング初心者が独学で1からPythonを学習し、資格取得・webアプリ作成まで。(資格取得編)
VScodeでPython、HTML/CSSコードを自動で整形する方法 プログラミング
VScodeでPython、HTML/CSSコードを自動で整形する方法

記事へコメントする

コメント一覧(0件)

Share

Top