Django超入門シリーズ(ブログを作るチュートリアル) ~ その3 Djangoの「プロジェクト、アプリ」とは何か?~

Django超入門

DjangoBabyのロゴ

前回の記事では「リクエストとレスポンス」というWebの大切な基本を学びました!サイトの閲覧者が、URLで欲しい情報を伝えてサーバーがそれを解釈して返答するということが徐々に理解できたかと思います。

今回はDjango特有の表現である「プロジェクト、アプリ」について学んで行きましょう。この2つはDjangoでは特殊な意味を持ちます。

本記事での目標

前回の記事ではurlpatternsと関数を同じファイル(=config/urls.py)に記述していきました。開発の最初の方はこれでも見やすいです。

しかし「ブログ機能だけでなくTodo機能もつけたい?」、「SNS機能もつけたいなぁ」とやりたいことが多くなるとどうでしょうか?

コード量が多くなるにつれて↓のように、urls.pyが何千、何万行と膨大になりそうなのは容易に想像できると思います。


from django.contrib import admin
from django.urls import path, include
from django.http import HttpResponse

def blog_list_func(request):
    return HttpResponse('blog list')

def blog_detail_func(request,pk):
    return HttpResponse('blog list')
    ・
    ・
    ・
def sns_hogehoge_func(request):
    # 処理
    return HttpResponse('sns hogehoge')

urlpatterns = [
    path('admin/', admin.site.urls), 
    path('blog/',blog_list_func), 
    path('blog/<int:pk>',blog_detail_func), 
    path('blog/like',blog_like_func), 
    ・
    ・
    ・
    path('todo/',todo_list_func), 
    path('todo/<int:pk>',todo_detail_func), 
    path('todo/like',todo_like_func), 
    path('sns/',sns_list_func), 
    path('sns/<int:pk>',sns_detail_func), 
    path('sns/like',sns_like_func), 
 # ・・・・・・どんどんコードが多くなる、、。
]

ここで 1. 「todo, blog, snsは別のフォルダにそれぞれまとめたい」、2. 「関数は別のファイルに分けて書きたい」という欲が出てきます。

今回はきれいにフォルダ、ファイルを整理することを通して、本記事では、Djangoの「プロジェクト」、「アプリ」の意味やそれらの違いについて学んでいきましょう🔥

startappコマンドを実行してみましょう

ブログの機能を作りたいとなったら、あらたにターミナルでコマンドを実行してみましょう

docker compose run --rm web python manage.py startapp blog

blogフォルダができました!

Djangoでは、このblogはアプリ、configはプロジェクトと名前がついています。

このようなディレクトリ構成になっているはずです。

.
├── Dockerfile
├── README.md
├── blog
│   ├── __init__.py
│   ├── admin.py
│   ├── apps.py
│   ├── migrations
│   ├── models.py
│   ├── tests.py
│   └── views.py
├── config
│   ├── __init__.py
│   ├── __pycache__
│   ├── asgi.py
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
├── docker-compose.yml
├── manage.py
└── requirements.txt

Djangoにおいて、「プロジェクト」、「アプリ」とは何か?

Djangoでのプロジェクトは「設定ファイルの集合体」、アプリは「あるまとまった機能の単位」と覚えると一番納得しやすいです。

URLの処理の流れ

1.「todo, blog, snsは別のフォルダにそれぞれまとめたい を解決するため、Djangoではconfig/urls.pyだけでなく、blogやtodoなどのアプリのフォルダ内にもurls.pyを作成します。

そのため、blogフォルダの中にurls.pyを作成してください。

config/urls.pyは各アプリのurls.pyへ振り分ける役割

アプリ名/urls.pyは前の記事のようにリクエストと関数を対応させる役割

のように役割分担します。イメージとしてはこんな感じです

これをコードで書くと

from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls), # 管理サイト用
    path('blog/',include('blog.urls')), # Blogアプリへ振り分ける
    path('todo/',include('todo.urls')), # Todoアプリへ振り分ける
    path('sns/',include('sns.urls')), # SNSアプリへ振り分ける
]

このconfig/urls.pyで、「/blog/〇〇に来たものはblogのurls.pyに、/todo/〇〇に来たものはtodoのurls.pyに」振り分けることができるようになります。

では、http://localhost:4989/blog/likeとリクエストが来たときを考えてみましょう。

このときblogのurls.pyは、urlpatternsの中の/blogは省略し、↓のように書いてください。

from django.urls import path

app_name = 'blog'

def blog_like_func(request):
    # ブログにいいねをする機能
    return HttpResponse('いいねしました')

urlpatterns = [
    path('like',blog_like_func), 
]

これで処理ができるようになりました。

Djangoにおけるviews.pyの役割

blogフォルダの中身を見るとviews.pyが自動で作成されているのがわかります。

Djangoでは、2. 「関数は別のファイルに分けて書きたい」 を解決するため、views.pyにレスポンスを返す関数を記述するというおおまかな決まりがあります。

コードの書き方

それでは実際にコードを書き始めましょう!以下の3つのファイルを書き換えてください。

config/urls.py

from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('blog/',include('blog.urls')), # Blogアプリへ振り分ける
]

blog/urls.py

from django.urls import path
from . import views

app_name = 'blog'

urlpatterns = [
    path('sample',views.blog_sample),
]

blog/views.py

from django.http import HttpResponse

def blog_sample(request):
    return HttpResponse('blogアプリの作成完了!')

ここまで書けたら、ブラウザで、http://localhost:4989/blog/sample にアクセスしてみてください。

どのように動いているか復習しましょう

まずリクエストを受けるのはconfig/urls.pyですね。

config/urls.pyはリクエストのURLを見て、/blog/とついているのでblog/urls.pyに処理を渡します。

blog/urls.pyは/blog/sampleの、/sampleの部分をチェックし対応する関数を決めます。

関数はviews.pyに書くという決まりにしたがって、blog/urls.pyの2行目でviewsをインポートしviews.blog_sampleという関数に処理を渡します。

そしてblog_sample関数はページを表示します。

まとめ

処理の流れは、

プロジェクト(=config)のurls.py → 担当するアプリのurls.py → 担当する関数

ということが理解できれば今回は大丈夫です。