前回からの続き
今回は前回表示できていなかった、画像を表示していきたいと思います。
staticファイルの公開
画像とかjsとかcssとかのいわゆるstaticファイルと呼ばれる。
これをDjangoで扱うには、ちょっと作業がいる。
適当なディレクトリに置いて、そのディレクトリを公開すればいいんじゃない?って考えてしまうのですが、Djangoには以下の機能が備わっているみたいです。
静的ファイルの公開方法 — Django 1.4 documentation
上記より抜粋。
小さなプロジェクトではこのことは大きな問題になりません。 Web サーバが見つけら れる場所で静的ファイルを単に管理することができるからです。しかし、もっと大きな プロジェクトで、特に複数のアプリケーションからなる場合は、各アプリケーションが 持っている静的ファイルの集まりを複数扱うことになり、ややこしくなってきます。
django.contrib.staticfiles はまさにそのためにあります。これは静的なファイルを各アプリケーションから (さらに指定した別の場所からも) 一つの場所に集め、運用環境で公開しやすくするものです。
大きなプロジェクトを作成しないと、有り難みがわからないかもしれませんが、ざっと見ていきます。
ヘッダー画像を表示する
まず、管理者画面から投稿した画像を表示する前に、通常の画像を扱う方法を見ていきます。
ここでは、以下のようにTOP画面のヘッダー画像を表示していきます。
前述の「django.contrib.staticfiles」ですが、setting.pyのINSTLLED_APPSに標準搭載されているのが確認できるので、特になにもしなくても使えそうです。
setting.py
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'posts',
]
そして、「django.contrib.staticfiles」は「setting.py」の「STATIC_URL」配下を探しにいくみたいです。
デフォルトでは、「/static/」が既に記載されています。
setting.py
STATIC_URL = '/static/'
このへんを確認したら、実際に表示したい画像を置きます。
アプリケーション「posts」配下にstaticディレクトリを新規に作成して、その配下にアプリケーション名「posts」のディレクトリを作成した上で、「home.jpg」を置きます。
└── posts
├── __init__.py
├── __pycache__
├── admin.py
├── apps.py
├── migrations
├── models.py
├── static
│ └── posts
│ └── home.jpg
前回のtemplatesもそうだったのですが、
アプリケーションのディレクトリ–>templates とか static とか–>アプリケーション名–>ファイル
という構成になってます。
(このへんの仕組みを書いたドキュメントがあったのですが、わからなくなっちゃいました。)
次に、html側を修正していきます。
以下のようにします。
home.html
{% load static%}
<img src="{% static "posts/home.jpg"%}" style="max-height:500px"/>
「{% load static %}」と 「{% static “ディレクトリ名” %}」を追加しています。
実際に、クライアントに返されるhtmlは以下の通りとなります。
home.html
<img src="/static/posts/home.jpg" style="max-height:500px"/>
実際にTOP画面にアクセスすると、画像が表示されることが確認できるかと思います。
管理者画面で投稿した画像を表示する
次に、管理者画面で投稿した画像を表示していきます。
現在の状態ですが、html側のソースを見てみると、「media/pinky2.jpg」となっていることが確認できます。
home.html
<h3> 彼女とデートなう</h3>
<p> June 5, 2017, midnight</p>
<img src="media/pinky2.jpg"/>
<p> 彼女ともんじゃ焼きを食べに行きました </p>
クライアントに返す前の状態はこんな感じでした。
home.html
{% for post in posts.all %}
<h3> {{ post.title }}</h3>
<p> {{ post.pub_date }}</p>
<img src="{{ post.image.url }}"/>
<p> {{ post.body }} </p>
{% endfor %}
そもそもmediaディレクトリってなんだっけ?ってなったのですが、
Postクラスのimageにアップロード先のディレクトリを定義していました。
class Post(models.Model):
image = models.ImageField(upload_to='media/')
そして、管理者画面から投稿した画像は、mediaディレクトリに置かれてますね。
├── db.sqlite3
├── manage.py
├── media
│ ├── django?\205??\226\200.png
│ ├── jingyi-wang-195381.jpg
│ ├── pinky2.jpg
│ └── remi-skatulski-88995.jpg
├── ohankyblog
なのでここでやりたいことはヘッダー画像のようにstaticディレクトリ配下に置いたものを見せる、というものではなく
管理者画面で投稿したmediaディレクトリ配下に置いたものを見せる、ということになります。
あんまりしっくりきてないのですが、メモがてら書きます。
さらにいえば、こんへんのやり方は開発環境用のもので実際に運用する際にはいろいろと問題があるみたいです。
最終的にはインターネットの世界に公開していきたいので、どこかでちゃんとした運用を紹介できればと思います。
まず、「setting.py」に「MEDIA_URL」と「MEDIA_ROOT」を追加しています。
setting.py
STATIC_URL = '/static/'
MEDIA_URL = '/pics/'
MEDIA_ROOT = BASE_DIR
次に、urls.pyを以下のように編集しています。
urls.py
from django.conf.urls import url
from django.contrib import admin
import posts.views
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^$',posts.views.home, name='home'),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
こうすることで、あら不思議、管理者画面で投稿した画像たちが表示されます。
実際のhtmlソースは以下のように編集されています。
<h3> 彼女とデートなう</h3>
<p> June 5, 2017, midnight</p>
<img src="/pics/media/pinky2.jpg" style="max-height:300px"/>
<p> 彼女ともんじゃ焼きを食べに行きました </p>
setting.pyで設定した「MEDIA_URL」は画像が置かれているディレクリを指定しているわけではなく、URLでどう見せるのかという設定だということがわかります。
なんでDjangoはmediaディレクトリに画像があるって知ってるんだろうなぁ、とか考えていたのですが
Postsクラスのimageフィールドがあるのか、思ったら納得しました。
試しに、sqliteでテーブルの中身を確認したところ、imageフィールドには、画像のパスが定義されていました。
(media以外にも格納先を「tekitou」とかに変えてみたりしていました)
sqlite> select * from posts_post2;
id = 1
title = aaaa
pub_date = 2017-06-10 11:26:18
body = aaaaaa
image = tekitou/pinky2.jpg
ちょっと中途半端ですが、今回はここまでです。