DjangoチュートリアルをRailsと比較しながらやってみた
はじめに
こんにちは!最近Djangoチュートリアルに取り組んでみました。今回はDjangoの公式チュートリアルを実際にやってみて、その経験をもとにRailsと比較してみたいと思います。私はフレームワークの中ではRailsによく親しみがあるため、Djangoの特徴や違いがどのように感じられるかを中心にまとめてみました。
アーキテクチャパターンの呼び方の違い
まず最初に、DjangoとRailsではアーキテクチャパターンの呼び方が異なります。
| 概念 | Django (MVT) | Rails (MVC) |
|---|---|---|
| モデル、DBのテーブルと紐づくレイヤー | Model | Model |
| HTMLを返すレイヤー | Template | View |
| リクエスト/レスポンスを管理するレイヤー | View | Controller |
DjangoはMVT(Model-View-Template)パターン、RailsはMVC(Model-View-Controller)パターンと呼ばれますが、役割としてはほぼ同じです。
ただし、DjangoのViewはRailsのControllerに相当するという点が最も混乱しやすいポイントですね。
ルーティングの管理方法の違い
DjangoのURLConfとRailsのルーティングは、どちらも「URLをどの処理に結びつけるか」を決める仕組みという点では同じです。しかし、その管理方法には大きな違いがあります。
| 項目 | Rails | Django |
|---|---|---|
| ファイル名 | config/routes.rb |
urls.py |
| 管理方式 | 中央集権的(全ルートを1つのファイルで管理) | 分散型(アプリごとに分割) プロジェクト全体の urls.pyが入口となり、各アプリのurls.pyをinclude()で取り込む |
Rails: 中央集権的なルーティング
# config/routes.rb
Rails.application.routes.draw do
resources :polls
resources :comments
# すべてのルートをここに記述
end
Railsでは、アプリケーション全体のルーティングを1つのファイルで一元管理します。プロジェクトのどこにどんなURLがあるのか、routes.rbを見ればすべて分かるように設計されています。
Django: 分散型のルーティング
一方、Djangoのurls.pyは分散型の設計です。
プロジェクト全体の入り口となるurls.pyがあり、そこから各アプリのurls.pyをinclude()で読み込みます。
# プロジェクト全体の入口のurls.py
from django.contrib import admin
from django.urls import include, path
urlpatterns = [
path("polls/", include("polls.urls")), # pollsアプリのURLを取り込む
path("comments/", include("comments.urls")), # commentsアプリのURLを取り込む
#... 他のアプリも同様
]
# polls/urls.py(pollsアプリ専用のルーティング)
from django.urls import path
from . import views
urlpatterns = [
path("", views.index, name="index"), # /polls/ にアクセスするとviews.indexが呼ばれる
path("<int:question_id>/", views.detail, name="detail"), # /polls/1/ など
path("<int:question_id>/results/", views.results, name="results"),
# ... 他のパスも同様
]
DjangoとRailsのModelの違い
DjangoとRailsのModelは、どちらもORM(Object-Relational Mapping)を提供しますが、いくつかの違いがあります。
| 項目 | Rails | Django |
|---|---|---|
| テーブルのデータの紐づけ(同じ部分) | ORMとしてデータの取得・作成・更新を行う | ORMとしてデータの取得・作成・更新を行う |
| スキーマ定義 |
db/schema.rbに自動生成 |
Migrationで管理(Modelから生成) |
| マイグレーション |
db/migrate/に個別ファイル |
Modelから自動生成 |
管理画面機能の比較
個人的に最も驚いたのがDjango Adminです。本格的なデータ管理画面が、標準機能として提供されています。
| 項目 | Rails | Django |
|---|---|---|
| 標準機能 | なし | Django Admin(標準搭載) |
| 実現方法 | ActiveAdmin、RailsAdminなどのgemが必要 | 最初から組み込み済み |
| 主な機能 | - | データベースレコードのCRUD操作 検索・フィルタリング ユーザー権限管理 |
Django Adminでできることは以下の通りです。
- データベースのレコードの閲覧・編集・削除
- モデルごとのCRUD操作
- 検索やフィルタリング機能
- ユーザー権限管理
これがフレームワークに最初から組み込まれているのは、Railsユーザーとしては新鮮でした。
HTTPメソッドの扱いの違い
ここは最も戸惑った部分です。Railsに慣れていると、ルーティングファイルを見ればHTTPメソッドが一目瞭然なのですが、Djangoでは少し事情が異なります。
| 項目 | Rails | Django (Function-Based View) | Django (Class-Based View) |
|---|---|---|---|
| 定義場所 | ルーティングファイル(routes.rb) |
ビュー(コントローラー)内 | クラスのメソッド名 |
| 定義方法 |
resourcesで一括生成 |
パスのみ定義し、ビュー側でrequest.methodにより分岐 |
HTTPメソッドに対応したメソッド名(get, post等)で定義 |
| 可視性 | ルーティングファイルで全体像を把握可能 | ビューのコードを読まないと判断できない | クラスのメソッド名である程度推測可能 |
Railsのアプローチ
resources :posts
# これだけで以下が生成される
# GET /posts -> index
# POST /posts -> create
# GET /posts/:id -> show
# PATCH /posts/:id -> update
# DELETE /posts/:id -> destroy
ルーティングファイルを見れば、どのURLがどのHTTPメソッドに対応しているかが明確です。
Django: Function-Based Viewのアプローチ
# urls.py
urlpatterns = [
path('posts/', views.post_list),
path('posts/<int:pk>/', views.post_detail),
]
# views.py
def post_detail(request, pk):
if request.method == 'GET':
# 取得処理
elif request.method == 'POST':
# 作成処理
elif request.method == 'DELETE':
# 削除処理
この設計は、同じURLに対して複数のHTTPメソッドを柔軟に処理できる反面、ルーティングファイルだけではAPIの全体像が把握しにくいと感じました。
Django: Class-Based Viewのアプローチ
Djangoチュートリアルでは扱われていませんが、DjangoにはClass-Based View(CBV)という選択肢もあります。これはRailsのコントローラーに近い感覚で使えそうです。
# urls.py
from django.urls import path
from .views import PostListView, PostDetailView
urlpatterns = [
path('posts/', PostListView.as_view()),
path('posts/<int:pk>/', PostDetailView.as_view()),
]
# views.py
from django.views import View
from django.views.generic import ListView, DetailView
# 汎用ビューを使う場合(よりシンプル)
class PostListView(ListView):
model = Post
template_name = 'posts/list.html'
context_object_name = 'posts'
class PostDetailView(DetailView):
model = Post
template_name = 'posts/detail.html'
context_object_name = 'post'
# または、基本のViewクラスを使う場合
class PostDetailView(View):
def get(self, request, pk):
# GET処理
post = Post.objects.get(pk=pk)
return render(request, 'posts/detail.html', {'post': post})
def post(self, request, pk):
# POST処理
pass
def delete(self, request, pk):
# DELETE処理
pass
Class-Based Viewを使うと、以下のメリットがあります。
- HTTPメソッドごとにメソッドを分離できる(
get(),post(),put(),delete()等) - コードの見通しが良くなる
個人的には、Function-Based Viewよりも、このClass-Based Viewの方がRailsユーザーには馴染みやすいと感じました。
まとめ
| 比較項目 | Rails | Django |
|---|---|---|
| アーキテクチャ | MVC | MVT(ViewとTemplateの呼び方が逆) |
| ルーティング | 中央集権的(1ファイルで管理) | 分散型(アプリごとに分割) |
| モデル設計 | スキーマとマイグレーションが分離 | Modelクラスが全てを統合 |
| 管理画面 | gemの追加が必要 | 標準搭載(Django Admin) |
| HTTPメソッド | ルーティングで明示 | FBV: ビュー内で分岐処理 CBV: メソッド名で分離 |
おわりに
正直なところ、最初は「Pythonで書くRails」程度の認識でDjangoに触れましたが、実際に使ってみるとまったく異なる設計思想を持つフレームワークでした。
- Django Admin の完成度の高さ: これが標準というのは驚きでした
- 分散型のルーティング: アプリごとにurls.pyを持つ設計は、Railsの中央集権的な管理とは対照的なアプローチでした
- HTTPメソッドの扱い方: ルーティングではなくビュー側で分岐する設計は、Railsとは真逆のアプローチでした
実際のプロジェクトでDjangoを使って、さらに理解を深めていきたいと思います!
Discussion