前回からの続き
tohutokonsome.hatenablog.com
前回は、Djangoで作成したプロジェクトに対して、手動でviews.pyを作成して、簡単なWebページを作成した。
今回はよりDjangoらしい機能を使っていきます。
今回作成するもの
以下のようなブログサイトを作成してみたいと思います。
TOP画面
詳細画面
プロジェクトの作成とモデルの作成
前回同様に、まずプロジェクトを作成します。
ブログサイトの名前は「ohankyblog」としました。
masao-3:myblog konoe_mario$ django-admin startproject ohankyblog
そして、前回と大きく異なる点として、「startapp」なるコマンドを用いてアプリケーションを作成します。
記事を管理するアプリケーションということで、「posts」とします。
アプリケーションがどういった単位で作成すべきなのか、という点がイメージできていませんが、とりあえず続行します。
masao-3:myblog konoe_mario$ python manage.py startapp posts
この「startapp posts」とすることで、新たにpostsディレクトリとその配下にいろいろなファイルが追加されているのが確認できます。
masao-3:myblog konoe_mario$ tree
.
├── manage.py
├── ohankyblog
│ ├── __init__.py
│ ├── __pycache__
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
└── posts
├── __init__.py
├── admin.py
├── apps.py
├── migrations
│ └── __init__.py
├── models.py
├── tests.py
└── views.py
その配下のファイルには、前回手動で作成した、「views.py」が作成されていることに気づきます。
きっと、作成されたviews.pyにHTTPリクエストから呼ばれる関数を書くんだな、と想像できますね。
templatesとhome.htmlの作成
とりあえず、前回と同様にトップ画面を作成していきます。
トップ画面である、home.htmlファイルを以下のようにtemplatesディレクトリ配下におきます。
templatesディレクトリの中にさらにpostsディレクトリを置く意図がいまいちわかりませんが、こちらもUdemyの動画にならいます。
home.htmlはこの段階では適当な内容なので、内容は割愛します。
└── posts
├── __init__.py
├── __pycache__
├── admin.py
├── apps.py
├── migrations
├── models.py
├── templates
│ └── posts
│ └── home.html
├── tests.py
└── views.py
views.pyとurls.pyの編集
このへんは慣れてきました。
posts配下のviews.pyにhome.htmlを返す関数と、urls.pyにurlの情報を定義します。
views.py
from django.shortcuts import render
def home(request):
return render(request, 'posts/home.html')
urls.py
from django.conf.urls import url
from django.contrib import admin
import posts.views
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^$',posts.views.home, name='home'),
]
前回は言われるがままに書いていましたが、「r'^$‘」って正規表現で、「^」は先頭一致、「$」は末尾一致で、組み合わせることで何も入力されていない(つまり、ルートディレクトリである)ことを表現している気がします。
setting.pyの編集
urls.pyとviews.pyを編集したらもう参照できるかな?と思いきや、前回定義したhome.htmlの場所を定義していません。
前回は、setting.pyのTEMPLATESに記載しましたが、startappでアプリケーションを作成する正規の方法では、setting.pyのINSTALL_APPSに作成したアプリケーション「posts」を追加すればいいみたいです。
setting.py
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'posts', <----これ
]
これを行うことで、Djangoはpostsアプリケーションがあるんだなって認識してくれるみたいです。
この状態でrunserverして、ルートディレクトリにアクセスすれば、home.htmlが表示されるかと思います。
モデルの作成
さて、モデルというものがここででてきます。
いまいちよくわかってませんが、データをもってるクラスって思っていればいいのかもしれません。
MVCモデルのMの部分だよってことなのかな。
※このへんをみるとモデルとは、データベースの定義と追加のメタデータの定義とある。
はじめての Django アプリ作成、その 1 — Django v1.0 documentation
さっそく、posts配下にあるmodels.pyを編集していきます。
└── posts
├── __init__.py
├── __pycache__
├── admin.py
├── apps.py
├── migrations
├── models.py <---これ!
├── templates
│ └── posts
│ └── home.html
├── tests.py
└── views.py
編集した内容は以下の通りです。
models.py
from django.db import models
class Post(models.Model):
'''
記事の内容を管理するクラスと思われる。
modelの定義はここに詳しく書いてある。
https://docs.djangoproject.com/ja/1.11/ref/models/fields/
'''
title = models.CharField(max_length=250)
pub_date = models.DateTimeField()
image = models.ImageField(upload_to='media/')
body = models.TextField()
いろいろとでていますが、 記事の内容を構成する要素を定義しています。
気になる、models.CharField()あたりですが、これがデータの型を表しているみたいです。
title要素は、Char型の要素ですよ、っていうのと、引数にmax_lengthを与えることで最大250文字ってことを定義しているみたいです。
詳細は以下に書いてあります。
モデルフィールドリファレンス | Django documentation | Django
さてさて、ここで「title」は「Char型」だよと定義する意味なんですが、冒頭の「モデルとはデータベースの定義」ということを思い出します。
つまり、ここで定義したデータ型をもつPostsテーブルをDjangoが作成してくれるみたいです。
テーブルっていっても、データベースなんかどこにあるんだっけ、と思ったのですが、setting.pyをみたりすると、sqlliteなる記述を発見できるかと思います。
つまり、デフォルトでsqlliteというデータベースが存在しているみたいです。
makemigrationとmigration
モデルに情報を定義したら、その次は、「makemigration」と「migration」コマンドを実行します。
一旦、テスト用のWebサーバーを起動していたら、落としときます。
※必須じゃないかも。
「makemigration」を実行することで、さきほどのモデルに定義した情報をもとにファイル「0001_initial.py」が作成されます。
masao-3:myblog konoe_mario$ python3 manage.py makemigrations
Migrations for 'posts':
posts/migrations/0001_initial.py
- Create model Posts
これは、DBのスキーマを作成するためのpythonコードが書かれているみたい。
sqlmigrateコマンドを実行すことで、DDL文の形式で確認することができます。
masao-3:ohankyblog konoe_mario$ python manage.py sqlmigrate posts 0001
BEGIN;
--
-- Create model Post
--
CREATE TABLE "posts_post" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT, "title" varchar(250) NOT NULL, "pub_date" datetime NOT NULL, "image" varchar(100) NOT NULL, "body" text NOT NULL);
COMMIT;
そして、このDDL文を実行するコマンドが、「migrate」になります。
masao-3:ohankyblog konoe_mario$ python manage.py migrate
Operations to perform:
Apply all migrations: admin, auth, contenttypes, posts, sessions
Running migrations:
Applying contenttypes.0001_initial... OK
Applying auth.0001_initial... OK
Applying admin.0001_initial... OK
Applying admin.0002_logentry_remove_auto_add... OK
Applying contenttypes.0002_remove_content_type_name... OK
Applying auth.0002_alter_permission_name_max_length... OK
Applying auth.0003_alter_user_email_max_length... OK
Applying auth.0004_alter_user_username_opts... OK
Applying auth.0005_alter_user_last_login_null... OK
Applying auth.0006_require_contenttypes_0002... OK
Applying auth.0007_alter_validators_add_error_messages... OK
Applying auth.0008_alter_user_username_max_length... OK
Applying posts.0001_initial... OK
Applying sessions.0001_initial... OK
初回のmigrateなんで、いろいろでてる。
postsも表示されているので、うまくいったみたい。
さきほど、モデルを編集して、migrateして〜みたいなことをしたので、sqlliteにPostsモデルの定義をもつテーブルが作成されたはずです。
では、実際に作成したテーブルに値を入れるにはどうしたらいいんだろう、ということで、前回スルーした以下のDjango管理者画面について触れていきます。
from django.conf.urls import url
from django.contrib import admin
from . import views
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^ohankyworld/', views.ohankyworld),
]
「http://localhost:8000/admin」にアクセスすると、以下のような画面が開きます。
Djangoはこの管理画面からさきほど作成したモデルのデータを作成することができます。
管理ユーザーの作成
まず、管理画面を使用するユーザーを作成する。
「createsuperuser」でuser名とアドレス(適当)、パスワードを設定して、サクッとつくります。
masao-3:ohankyblog konoe_mario$ python manage.py createsuperuser
Username (leave blank to use 'konoe_mario'): admin
Email address: admin@admin.jp
Password:
Password (again):
Superuser created successfully.
管理画面をさわってみる
ログインすると、以下の画面が表示されます。
が、このままでは作成したPostモデルを触ることができません。
編集できるようにするには、「admin.py」に以下の定義を追加する必要があります。
admin.py
from django.contrib import admin
from .models import Post
admin.site.register(Post)
定義を追加したあとに、管理者画面をリロードすると、以下のように作成したモデル(というよりアプリケーション?)が追加されます。
追加されたPostをクリックすると、まだなんもない状態であることがわかります。
そこから画面右上のADD POSTを押下します。
そうすると、以下の画面のように、モデルに定義したフィールドを持つ入力画面が表示されるではありませんか!
さっそくデータを適当に入力してみました。
さらにさらに、合計4件ほど追加しました。
「Post object」なるものが4件ほどあるのがわかるかと思います。
管理者画面で作成したデータをpythonでさわる
さきほど管理者画面で作成したデータをviews.pyからさわります。
さわるといっても、すごく簡単です。
from django.shortcuts import render
from .models import Post
def home(request):
posts = Post.objects.order_by('pub_date')
return render(request, 'posts/home.html',{'posts':posts})
postモジュールをimportするだけです。
取得したモデルは、前回同様、ディクショナリ形式でrender関数に渡すだけで、html側で参照できます。
home.html側はこんな感じです。
home.html
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
{% for post in posts.all %}
<h3> {{ post.title }}</h3>
<p> {{ post.pub_date }}</p>
<img src="{{ post.image.url }}"/>
<p> {{ post.body }} </p>
{% endfor %}
</body>
</html>
上記、定義を追加したあとに実際に「http://localhost:8000/」にアクセスすると、
管理者画面から追加した内容が表示されていることが確認できます。
※イメージが表示できてないのは個別で設定が必要。
一旦、ここまでをまとめ
関係性をかんたんに書きました。
長くなったので、次回に続くかもです。
次回
tohutokonsome.hatenablog.com