[実行環境]
Win10
python 3.7.7(64bit)
pip 20.1.1
pipenv 2020.6.2
Django 3.0.7
postgreSQL 12.3
Djangoのインストール
まずは、仮想環境を作成して最新のDjangoをインストール。
はじめての Django アプリ作成、その 1 | Django ドキュメント | Django
> mkdir 20200619_diango_ver_3 > cd 20200619_diango_ver_3 > pipenv install django Creating a virtualenv for this project… ...略...
pipenvのシェルを有効にして、
> pipenv shell
プロジェクトの作成。
(.venv) > django-admin startproject mysite
開発用サーバーの起動(いくつか警告が出ますが無視します)
(.venv) > cd mysite (.venv) > python manage.py runserver Watching for file changes with StatReloader Performing system checks... ...略...
http://127.0.0.1:8000/にアクセスすると、"Congratulations!"と表記されたロケットの離陸ページが出ます。
続いてアプリケーションを作ります。
Djangoにはプロジェクトとアプリケーションという概念があります。
プロジェクトとアプリケーション
プロジェクトとアプリの違いは何でしょうか? アプリとは、ウェブログシステム、公的記録のデータベース、小規模な投票アプリなど、何かを行う Web アプリケーションです。プロジェクトは、特定のウェブサイトの構成とアプリのコレクションです。プロジェクトには複数のアプリを含めることができます。 アプリは複数のプロジェクトに存在できます。
はじめての Django アプリ作成、その 1 | Django ドキュメント | Djangoより
bookはただのアプリケーション名なので任意です。
(.venv) > python manage.py startapp book
アプリケーションを作成したら、mysite/book/views.pyを以下のようにして、
from django.http import HttpResponse def index(request): return HttpResponse("Hello, world!")
mysite/book/urls.pyを作成してviewとurlを紐つけます。
from django.urls import path from . import views urlpatterns = [ path('', views.index, name='index'), ]
mysite/mysite/urls.pyを変更してbookをルーティング。
from django.contrib import admin from django.urls import include, path urlpatterns = [ path('book/', include('book.urls')), path('admin/', admin.site.urls), ]
もう一度、サーバーを起動して、
(.venv) > python manage.py runserver
http://127.0.0.1:8000/book/にアクセスして「Hello, world!」が表示されたらOK。
DBの設計
ローカルにすでにtestdbというpostgreSQLの空っぽDBがあるとします。
はじめての Django アプリ作成、その2 | Django ドキュメント | Django
最初にpythonのPostgreSQLドライバpsycopg2をインストールしておきます。
ないとエラーが出ました。
(.venv) > pipenv install psycopg2 Installing psycopg2… ...略...
mysite/mysite/settings.pyを開けると、デフォルトではDBはsqliteが選ばれていて、
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.sqlite3', 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), }
それを以下のように変更します。
特にオンラインで使用する予定がないためパスなども直書きしてますが、herokuなどにデプロイする場合は隠蔽する必要があります。
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.postgresql', 'NAME': 'testdb', 'USER': 'hogehoge', 'PASSWORD': 'hogehoge', 'HOST': 'localhost', } }
ENGINEの項目は、以前は'django.db.backends.postgresql_psycopg2'という名前を使っていたようですが、要は同じだそうです。
python - What is the difference between postgres and postgresql_psycopg2 as a database engine for django? - Stack Overflow
Django内で使うフレームワークのためにDBに予め指定のテーブルがいるらしく、そのためにマイグレーションを実行します。
(.venv) > python manage.py migrate
Operations to perform:
Apply all migrations: admin, auth, contenttypes, 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 admin.0003_logentry_add_action_flag_choices... 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 auth.0009_alter_user_last_name_max_length... OK
Applying auth.0010_alter_group_name_max_length... OK
Applying auth.0011_update_proxy_permissions... OK
Applying sessions.0001_initial... OK
ローカルのDBを確認すると、Django関係のテーブルが色々と挿入されています。
testdb=# \dt リレーション一覧 スキーマ | 名前 | 型 | 所有者 ----------+----------------------------+----------+---------- public | auth_group | テーブル | hogehoge public | auth_group_permissions | テーブル | hogehoge public | auth_permission | テーブル | hogehoge public | auth_user | テーブル | hogehoge public | auth_user_groups | テーブル | hogehoge public | auth_user_user_permissions | テーブル | hogehoge public | django_admin_log | テーブル | hogehoge public | django_content_type | テーブル | hogehoge public | django_migrations | テーブル | hogehoge public | django_session | テーブル | hogehoge
モデルの作成
自作アプリケーションbookをプロジェクトに含めます。
settings.pyのINSTALLED_APPSに'book.apps.BookConfig'を追加します。
INSTALLED_APPS = [ 'book.apps.BookConfig', 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', ]
以前は'book'とアプリ名だけの追加でしたが、これもバージョンが上がって変わったようです。
python - Two ways of including an app in INSTALLED_APPS - Stack Overflow
テーブル構造は、Auhor(作者)とBook(本)という一対多の関係を考えてみます。
「一対一」「一対多」「多対多」のリレーションを分かりやすく説明する - akiyoko blog
mysite/book/models.pyを編集します。
Django 3.0 のモデルフィールドリファレンス一覧まとめ - Qiita
from django.db import models class Author(models.Model): name = models.CharField(verbose_name='名前', max_length=100) age = models.PositiveIntegerField(verbose_name='年齢') #__str__は管理画面で表示される無味乾燥なオブジェクト表記を作者名に改める def __str__(self): return self.name class Book(models.Model): #ForeignKeyは作者と著作本の、一対多のリレーションを作る author = models.ForeignKey(Author, verbose_name='作者', on_delete=models.CASCADE) name = models.CharField(verbose_name='名前', max_length=100) release_date = models.DateTimeField(verbose_name='発売日') def __str__(self): return self.name
モデルに変更を加えたら、それをmakemigrationsでDjangoに伝えます。
(.venv) > python manage.py makemigrations book Migrations for 'book': book\migrations\0001_initial.py - Create model Author - Create model Book
実行すると、mysite/book/migrationsフォルダの中に、0001_initial.pyというファイルができます。
# Generated by Django 3.0.7 on 2020-06-23 02:41 from django.db import migrations, models import django.db.models.deletion class Migration(migrations.Migration): initial = True dependencies = [ ] operations = [ migrations.CreateModel( name='Author', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('name', models.CharField(max_length=100, verbose_name='名前')), ('age', models.PositiveIntegerField(verbose_name='年齢')), ], ), migrations.CreateModel( name='Book', fields=[ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('name', models.CharField(max_length=100, verbose_name='名前')), ('release_date', models.DateTimeField(verbose_name='発売日')), ('author', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='book.Author', verbose_name='作者')), ], ), ]
モデルを編集してmakemigrationsするごとにマイグレーションファイルが作成され、変更履歴が追えるようになっています。
migrateを実行すると、それらはCREATE TABLE文などのpostgreSQLのコマンドとして実行されます。
(.venv) > python manage.py sqlmigrate book 0001 BEGIN; -- -- Create model Author -- CREATE TABLE "book_author" ("id" serial NOT NULL PRIMARY KEY, "name" varchar(100) NOT NULL, "age" integer NOT NULL CHECK ("age" >= 0)); -- -- Create model Book -- CREATE TABLE "book_book" ("id" serial NOT NULL PRIMARY KEY, "name" varchar(100) NOT NULL, "release_date" timestamp with time zone NOT NULL, "author_id" integer NOT NULL); ALTER TABLE "book_book" ADD CONSTRAINT "book_book_author_id_40846805_fk_book_author_id" FOREIGN KEY ("author_id") REFERENCES "book_author" ("id") DEFERRABLE INITIALLY DEFERRED; CREATE INDEX "book_book_author_id_40846805" ON "book_book" ("author_id"); COMMIT;
migrateすると、DBにAuthorとBookというテーブルが挿入されました。
(.venv) > python manage.py migrate
Operations to perform:
Apply all migrations: admin, auth, book, contenttypes, sessions
Running migrations:
Applying book.0001_initial... OK
testdb=# \dt リレーション一覧 スキーマ | 名前 | 型 | 所有者 ----------+----------------------------+----------+---------- public | auth_group | テーブル | hogehoge public | auth_group_permissions | テーブル | hogehoge public | auth_permission | テーブル | hogehoge public | auth_user | テーブル | hogehoge public | auth_user_groups | テーブル | hogehoge public | auth_user_user_permissions | テーブル | hogehoge public | book_author | テーブル | hogehoge public | book_book | テーブル | hogehoge public | django_admin_log | テーブル | hogehoge public | django_content_type | テーブル | hogehoge public | django_migrations | テーブル | hogehoge public | django_session | テーブル | hogehoge
DBを設計する場合、postgreSQLのコマンドを覚えるよりも、Djangoのモデルから作る方がずっと楽ですね。
管理画面からDBにアクセスする
adminサイトにログインするためのユーザーを作成します。
(.venv) > python manage.py createsuperuser
ユーザー名 (leave blank to use 'XXX'): testuser
メールアドレス: sample@example.com
Password:
Password (again):
Superuser created successfully.
runserverして、http://127.0.0.1:8000/admin/にアクセスします。
先ほど作成したユーザーで管理画面にログインすることができます。
管理画面にAuthorとBookが表示されていないので追加します。
mysite/book/admin.pyを以下のように編集します。
from django.contrib import admin from .models import Author, Book admin.site.register(Author) admin.site.register(Book)
再度管理画面にアクセスすると、無事表示されました。自動的に複数形になるようです。
管理画面から作家レコードを追加してみます。
追加できました。
ちなみに、モデルで__str__メソッドを指定しないと、以下のような味気ない表記になります。
著作も追加してみます。
作者の箇所が、一対多を表すリレーションです。時刻などは適当。
うまくいったようです。