#Djangoのurls.pyは上から順番にURLのパターンマッチを探すので、順番は大事!
ものすごく基本的なことですが、見落としていたことによってだいぶハマってしまったので反省を込めて記録。。。
(※この記事では、「現場で使えるDjango基礎編」(注)で提唱されているベストプラクティスを参考に
新規プロジェクト作成時に、自動で生成されるプロジェクトと同名のフォルダである
mysite/mysite
をmysite/config
に変更しております。
(プロジェクト名がmysiteの場合)
個人的には、このやり方、わかりやすくて非常に良いと思いました。)
#ハマったこと
管理サイトからブログ記事と写真をアップロードして、
HTML内で<img src="{{ post.image.url }}"
として写真ファイルを呼び出そうとしても表示されない。
意図通り、mysite/media ディレクトリ(config/settings.pyでMEDIA_ROOT
として指定したディレクトリ)を参照するようになっていますが、/media/haikei2.png
をクリックすると、トップ画面に移動してしまいます。
config.urls.py
を見てみると、
from django.conf.urls.static import static
from django.contrib import admin
from django.urls import path, include, re_path
from django.conf.urls import url
from django.views.generic import RedirectView
from django.conf import settings
urlpatterns = [
path('admin/', admin.site.urls),
path('top/', include('top.urls')),
path('posts/', include('posts.urls')),
re_path(r'\w*', RedirectView.as_view(url='/top/'), name='redirect_to_index')
]
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
当たり前じゃないか、と思う方も多いかもしれません。
そうです、
urlpatterns += re_path(r'\w*', RedirectView.as_view(url='/top/'), name='redirect_to_index')
このコードは、「ホスト名の後に存在しないパターンが入力された場合(コピペなどした後に何かのはずみで英数字を入れてしまったときなど)でも、トップ画面にリダイレクトしてくれるようにしよう」という意図で書いたものですが、このコードの位置が悪かったです。
この状態では、re_path関数の上のURL、(つまりadmin
, top
, posts
)以外のURLについては、一切合切がRedirectViewの対象となってしまいます。一番下のstatic~が置いてけぼりにされてしまっています。。
なので、このようにしたら、意図通りにmediaディレクト内のファイルを読み込んでくれるようになりました。
from django.conf.urls.static import static
from django.contrib import admin
from django.urls import path, include, re_path
from django.conf.urls import url
from django.views.generic import RedirectView
from django.conf import settings
urlpatterns = [
path('admin/', admin.site.urls),
path('top/', include('top.urls')),
path('posts/', include('posts.urls')),
]
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
urlpatterns += [re_path(r'\w*', RedirectView.as_view(url='/top/'), name='redirect_to_index')]
##結論: Djangoのurls.pyは上から順番にURLのパターンマッチを探すので、順番は大事!
そもそも、Pythonが
関数やクラスを含む変数を上から読む言語(「インタプリタ言語」と呼ばれる)
ですからね。