ユーニックス総合研究所

  • home
  • archives
  • python-django-linebbs-urls-views

Django入門: ルートとビューの接続 ~ 簡単な一行掲示板アプリを作る その5【Windows10】

  • 作成日: 2020-10-17
  • 更新日: 2023-12-26
  • カテゴリ: Django

はじめに

この記事はDjangoで簡単な一行掲示板を作るシリーズ↓の記事です。

前回までにDjangoでプロジェクトとアプリを作成し、プロジェクトのurls.pyにアプリのurls.pyを指定する所までやりました。

今回からアプリのルート情報であるurls.pyを作成し、ルート情報とビューの接続をやっていきたいと思います。
この記事からDjangoのMVTの「V(View)」に触れることになります。

また、作業前のフォルダは例によってmanage.pyのあるフォルダに移動してください。
それから仮想環境がアクティベートされていることを確認してください。
アクティベートされていない場合はvenv\Scripts\activateを実行してコマンドプロンプトで仮想環境をアクティベートしてください。

プロジェクトのurls.pyからアプリのurls.pyを参照する

manage.pyのあるフォルダからlinebbsフォルダのurls.pyを参照すると現在は↓のようになっています。

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

urlpatterns = [  
    path('admin/', admin.site.urls),  
    path('bbs/', include('bbs.urls')),  # <- ここに注目  
]  

include()関数の引数であるbbs.urlsは「bbsアプリのurls.pyを参照する」という意味でした。
現在はこのbbs.urlsは定義されておらず、python manage.py checkを実行するとエラーになる状態です。
これから実際にbbs.urlsを定義します。

bbs\urls.pyの作成

manage.pyのあるフォルダから見たbbs\urls.pyを新規作成してください。
つまりbbsアプリのフォルダ内にurls.pyを作成します。
bbs\urls.pyには↓のように記述します。

from django.urls import path  
from bbs.views import home_view  # bbs\views.pyからhome_view関数をインポート  

urlpatterns = [  
    path('', home_view, name='bbs_home'),  # ルートにhome_viewを指定  
]  

↑でインポートしているビュー(home_view)はまだ定義していません。
Djangoではビューは関数やクラスで定義します。それらの定義はアプリのフォルダにあるviews.pyファイルかviews\フォルダ以下に定義するのが一般的です。
あくまで一般的と言うだけであって他の場所にビューを定義することも可能です。

↑のhome_viewは、これからbbs\views.py内に定義する予定です。
ですのでurls.pyには↑のようにインポートの記述を書いておきます。
urls.pyのルート情報とビューをどちらを先に定義するのかと言う話にもなりますが、今回のチュートリアルではトップダウン的に先にルート情報を定義しています。

それからurlpatterns内の↓の記述についてです。

    path('', home_view, name='bbs_home'),  # ルートにhome_viewを指定  

path()に指定しているパスが空文字列になっています。
これはどういうことかというと、このように空文字を指定することでアプリのパスのルートを指定しています。
前回のlinebbs\urls.pyではbbs\urls.pyに↓のように委譲していました。

    path('bbs/', include('bbs.urls')),  

↑これはbbs/以下のパスをbbs.urlsに委譲するという意味です。
これはbbs.urls内で定義するパスはbbs/で始まるという意味になります。
つまりbbs\urls.pyに↓のようにパスを定義した場合、

    path('brah/', brah_view, name='bbs_home'),  # brah/ に brah_view を接続  

↑のパスはhttps://localhost:8123/bbs/brah/への解決になります。
プロジェクトのurls.pyで指定したbbs/と、アプリのurls.pyで指定したbrah/がくっついてるわけですね。
これがルート情報の委譲の仕組みです。

よって↓のようにパスを空文字にした場合、

    path('', home_view, name='bbs_home'),  # ルートにhome_viewを指定  

パスはhttps://localhost:8123/bbs/への解決になります。
ということはこれは、アプリのルート(bbsアプリの/, つまりbbs/)への解決になるということですね。

name='bbs_home'とは?

↓のname='bbs_home'ですが、

    path('', home_view, name='bbs_home'),  # ルートにhome_viewを指定  

これはこのルートの名前です。
Djangoのルート情報には↑のように名前を付けることが出来ます。
この名前が必要になるケースですが、この名前はテンプレートファイル内から参照することが可能です。
Djangoのテンプレートファイルではパスを直書きするのではなく、↑のような名前を指定してパスを参照する仕組みが備わっています。
このようにすることでパスの変更を抽象化して、仕様変更につよいコードを書けるようになっているわけです。

bbs\views.pyの編集

では次にbbs\views.pyhome_view()関数を定義します。
これはパスbbs/に接続するビューです。

manage.pyのあるフォルダからbbs\views.py, つまりbbsアプリのフォルダ内にviews.pyをエディタで編集します。
bbs\views.pyの内容は↓のようになっています。

from django.shortcuts import render  

# Create your views here.  

コメントで「Create your views here.(ここにあなたのビューを作ってね)」と書かれていますね。
あとrenderという関数がインポートされています。
このrenderはテンプレートファイルを描画するための関数です。
よく使われるので最初から書かれているようです。

bbs\views.pyを↓のように編集します。

from django.shortcuts import render  
from django.http import HttpResponse  # <- この行を追加  


def home_view(request):  
    """  
    パス bbs/ のテンプレートを出力するビュー  
    """  
    return HttpResponse('Hello, World!')  # テスト。レスポンスを返す  

ビューではテンプレートファイルを描画するわけですが、今回はその前に簡単な「Hello, World!」をテンプレートファイルとは違う方法で出力してみます。
ここの「Hello, World!」でルート情報とビューの接続を確認し、確認が完了したらテンプレートファイルを定義すると言う風に進めます。
この方法は開発の分割統治で、問題を小さくするのに有効な方法でよく使われます。

🦝 < 無人島に持って行きたい分割統治

↑のコードを1つ1つ見ていきます。
まず↓のインポート文です。

from django.http import HttpResponse  # <- この行を追加  

django.httpモジュールからHttpResponseクラスをインポートしています。
このHttpResponseクラスはビューからの返り値、レスポンスを表現するクラスです。
HttpResponseを使うとテンプレートファイルを書かずにビューからレスポンスを返すことが出来ます。
今回のような簡略的な「Hello, World!」を出力したい時などに便利なクラスです。

次に↓の部分、ビューの定義です。

def home_view(request):  
    """  
    パス bbs/ のテンプレートを出力するビュー  
    """  
    return HttpResponse('Hello, World!')  # テスト。レスポンスを返す  

先述の通りビューは関数かクラスで定義します。
↑のhome_viewは見ての通り関数です。
引数にrequestを受け取っています。
このrequestはルートからビューに渡されるリクエストで、これはユーザーの使っているブラウザから送信されたHTTPリクエストをDjangoのオブジェクトとして抽象化したものです。
requestオブジェクトにはパスやクエリ、それからHTTPリクエストのヘッダの内容などがデータとして格納されており、各種メソッドや属性を参照することでそれらのデータにアクセスできます。
つまり、ビューでURLのパラメーター、クエリを参照したい時や、リクエストがGETメソッドかPOSTメソッドか知りたい時などは、このrequestを参照すればいいことになります。

次にreturn HttpResponse('Hello, World!')とやってビューからレスポンスを返しているところです。
HttpResponseは第1引数にレスポンスの内容を指定します。↑の場合、その内容は「Hello, World!」になっています。
ビューの関数は返り値として↑のようにレスポンスを返します。
Djangoはこのレスポンスをビューから受け取って、描画(ブラウザにレスポンスを返す、正確にはWebサーバーが)します。

コードの検証

これでルートとビューの仮接続は完了しました。
↓のコマンドでコードに潜在的な問題が無いかチェックします。

> python manage.py check  

特に問題が無ければ↓のように表示されます。

System check identified no issues (0 silenced).  

開発用サーバーによる動作確認

↓のコードで開発用サーバーを起動します。

> python manage.py runserver 0.0.0.0:8123  

↓のようなログが出力されプログラムが無限ループになります。

Watching for file changes with StatReloader  
Performing system checks...  

System check identified no issues (0 silenced).  

You have 18 unapplied migration(s). Your project may not work properly until you apply the migrations for app(s): admin, auth, contenttypes, sessions.  
Run 'python manage.py migrate' to apply them.  
September 19, 2020 - 19:40:15  
Django version 3.1.1, using settings 'linebbs.settings'  
Starting development server at http://0.0.0.0:8123/  
Quit the server with CTRL-BREAK.  

ちなみにpython manage.py runserverを実行する場合はpython manage.py checkを省略してもOKです。
python manage.py runserverもコードの検証に失敗したらエラーを出力してくれるからです。

ブラウザのアドレスバーにhttp://localhost:8123/bbs/と打ち込んでアクセスすると↓のように表示されます。

/のルート情報を設定する

今のままだと「http://localhost:8123/」にアクセスした場合、ページが表示されません。
これの解決方法は色々あります。
ルート(/)用のビューを作ったり、アプリのルート情報に委譲したりします。
今回のプロジェクトではルートはbbsアプリのビューを指定したいと思います。

manage.pyのあるフォルダに移動し、エディタでlinebbs\urls.pyを開き↓のように編集します。

from django.contrib import admin  
from django.urls import path, include  
from bbs.views import home_view  # <- この行を追加  

urlpatterns = [  
    path('admin/', admin.site.urls),  
    path('bbs/', include('bbs.urls')),  
    path('', home_view, name='root'),  # ←この行を追加  
]  

↑のようにパス('')に今回作成したbbsアプリのhome_viewを指定します。
これで「http://localhost:8123/」にアクセスしたら、bbsアプリのhome_viewが内容を描画するようになりました。
URLにアクセスすると「Hello, World!」と表示されます。

SEO的には「http://localhost:8123/」と「http://localhost:8123/blog/」の両方で同じページが表示されるので、/blogの方のページにnoindexを指定したほうが良いかもしれませんが、SEOについては今回は省略します。

おわりに

今回はルートとビューの仮接続を行いました。
次回からテンプレートファイルを作ってビューで描画してみたいと思います。

🐭 < 次回はMVTのTに進むよ