準備
前提、前回の復習
https://dev.to/kaede_io/docker-compose-de-django-tutorial-no-httpresponse-woque-ren-suru-67o
前回の記事で
- Docker Compose で Django + Postgres での環境構築
- ブラウザでのプロジェクトのトップ画面の動作確認
- polls アプリを作成して、ルーティングの動作確認
ここまでやった。
今回はその続き Django Tutorial Part 2 をやる
https://docs.djangoproject.com/en/4.0/intro/tutorial02/
migrate で初期化
https://docs.djangoproject.com/en/4.0/intro/tutorial02/#creating-models
docker-compose run web python manage.py migrate
Starting rest0406_db_1 ... done
Creating rest0406_web_run ... done
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 auth.0012_alter_user_first_name_max_length... OK
Applying sessions.0001_initial... OK
まずはこれで DB の初期化をする。
これで新しく DB を作る準備ができると推測する。
モデルファイルを作成して DB テーブルを作る
Question テーブルのモデルファイルを書く
次に DB テーブルを作るためのモデルのファイルを書く。
from django.db import models
class Question(models.Model):
question_text = models.CharField(max_length=200)
pub_date = models.DateTimeField('date published')
class Choice(models.Model):
question = models.ForeignKey(Question, on_delete=models.CASCADE)
choice_text = models.CharField(max_length=200)
votes = models.IntegerField(default=0)
Question とそれに関連する Choice のデータベースを作る
このふたつ、 Blitz のチュートリアルでも見たな...
モデルを読み込んで有効化する
https://docs.djangoproject.com/en/4.0/intro/tutorial02/#activating-models
これを読み込むためには projectName/settings.py
に追加の設定を書き込む必要がある。
INSTALLED_APPS = [
'polls.apps.PollsConfig',
'django.contrib.admin',
...
]
polls/ の一つ上のディレクトリの settings.py の
INSTALLED_APPS に 'polls.apps.PollsConfig',
を追加する
makemigrations で 初期化の準備ファイルを作る
By running makemigrations, you’re telling Django that you’ve made some changes to your models (in this case, you’ve made new ones) and that you’d like the changes to be stored as a migration.
makemigrations を動かすことで
Django に「モデルが変わったよ!」と伝えているらしい。
docker-compose run web \
python manage.py makemigrations polls
makemigrations コマンドを打つ。
docker-compose run web \
python manage.py makemigrations polls
Creating dockerdjango_web_run ... done
Migrations for 'polls':
polls/migrations/0001_initial.py
- Create model Question
- Create model Choice
これで初期化の準備ファイル
# Generated by Django 3.2.12 on 2022-04-09 08:24
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
initial = True
dependencies = [
]
operations = [
migrations.CreateModel(
name='Question',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('question_text', models.CharField(max_length=200)),
('pub_date', models.DateTimeField(verbose_name='date published')),
],
),
migrations.CreateModel(
name='Choice',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('choice_text', models.CharField(max_length=200)),
('votes', models.IntegerField(default=0)),
('question', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='polls.question')),
],
),
]
0001_initial.py が作成された。
このファイルを指定して sqlmigrate する。
sqlmigrate で SQL を発行する
docker-compose run web \
python manage.py sqlmigrate polls 0001
[+] Running 1/0
⠿ Container dockerdjango-db-1 Running 0.0s
BEGIN;
--
-- Create model Question
--
CREATE TABLE "polls_question" ("id" bigserial NOT NULL PRIMARY KEY, "question_text" varchar(200) NOT NULL, "pub_date" timestamp with time zone NOT NULL);
--
-- Create model Choice
--
CREATE TABLE "polls_choice" ("id" bigserial NOT NULL PRIMARY KEY, "choice_text" varchar(200) NOT NULL, "votes" integer NOT NULL, "question_id" bigint NOT NULL);
ALTER TABLE "polls_choice" ADD CONSTRAINT "polls_choice_question_id_c5b4b260_fk_polls_question_id" FOREIGN KEY ("question_id") REFERENCES "polls_question" ("id") DEFERRABLE INITIALLY DEFERRED;
CREATE INDEX "polls_choice_question_id_c5b4b260" ON "polls_choice" ("question_id");
COMMIT;
これで sql を発行する
migrate で sql を実行する
docker-compose run web \
python manage.py migrate
[+] Running 1/0
⠿ Container dockerdjango-db-1 Running 0.0s
Operations to perform:
Apply all migrations: admin, auth, contenttypes, polls, sessions
Running migrations:
Applying polls.0001_initial... OK
これで SQL を実行し、テーブルを作成できたと解釈する。
shell でインタラクティブモードでテーブルの中身を確認する
shell コマンドでインタラクティブモードを起動する
シェルモードで、実際にテーブルが作成されているのか確認する。
https://docs.djangoproject.com/en/4.0/intro/tutorial02/#playing-with-the-api
shell コマンドを実行すると
docker-compose run web \
python manage.py shell
[+] Running 1/0
⠿ Container dockerdjango-db-1 Running 0.0s
Python 3.10.0 (default, Oct 16 2021, 10:05:15) [GCC 10.2.1 20210110] on linux
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>>
インタラクティブ コンソールが起動する。
Questions の中身を objects.all() で確認する
>>> from polls.models import Choice, Question
Question.objects.all()
<QuerySet []>
migrate で作成した polls アプリのモデルの
Choice, Questions のテーブルをシェルでインポートして
Question の objects.all() で中身を見る。
すると空のクエリセットが帰ってくる。
クエリセットは JSON に変換する前の状態だと解釈する
Question に question_text と pub_date のデータを入れる
from django.utils import timezone
pub_date で使うので timezone のライブラリをインポートする
q = Question(question_text="What's new?", pub_date=timezone.now())
Question モデルの中に
- question_text という変数名で What's new? というテキスト
- pub_date という変数名で timezone.now() の現在の時間 これらを入れ、それを q という変数に入れる。
>>> q
<Question: Question object (None)>
>>> q.question_text
"What's new?"
変数の q そのものに アクセスしても Object (None) になってしまうが
q.question_text にアクセスすると中身の文字列が返ってくる
>>> q.id
>>>
id は最初はない。
>>> q.save()
>>> q.id
1
save() すると id が決まる。
>>> q.pub_date
datetime.datetime(2021, 12, 19, 13, 17, 26, 609289, tzinfo=<UTC>)
pub_date にアクセスすると datetime がこのように返ってくる。
>>> q.objects.all()
Traceback (most recent call last):
File "<console>", line 1, in <module>
File "/usr/local/lib/python3.10/site-packages/django/db/models/manager.py", line 179, in __get__
raise AttributeError("Manager isn't accessible via %s instances" % cls.__name__)
AttributeError: Manager isn't accessible via Question instances
q に objects.all() でアクセスしても中身は見えない。
>>> Question.objects.all()
<QuerySet [<Question: Question object (1)>]>
Question モデルに直接 objects.all() することで中身を見れる
しかしこれだと中身の詳細出てこないので、
objects.all() をしただけでモデルの詳細まで出るようにする。
str を追加して text の中身を見えるようにする
class Question(models.Model):
question_text = models.CharField(max_length=200)
pub_date = models.DateTimeField('date published')
def __str__(self):
return self.question_text
class Choice(models.Model):
question = models.ForeignKey(Question, on_delete=models.CASCADE)
choice_text = models.CharField(max_length=200)
votes = models.IntegerField(default=0)
def __str__(self):
return self.choice_text
polls/models.py の Question と Choice のクラスに
__str__
という関数を追加する。
>>> exit()
kaede0902@rooter rest0406 %
docker-compose run web \
python manage.py shell
[+] Running 1/0
⠿ Container dockerdjango-db-1 Running 0.0s
Python 3.10.0 (default, Oct 16 2021, 10:05:15) [GCC 10.2.1 20210110] on linux
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
反映させるためにシェルを再起動
>>> from polls.models import Choice, Question
>>> Question.objects.all()
<QuerySet [<Question: How Are You?>]>
これで Question の中身を見る時に、object の中身の text が表示されるようになった!
条件でクエリする
>>> Question.objects.filter(id=1)
<QuerySet [<Question: How Are You?>]>
>>> Question.objects.filter(id=2)
<QuerySet []>
>>> Question.objects.filter(question_text__startswith='H')
<QuerySet [<Question: How Are You?>]>
filter, startswith,
でカラムの中身で検索することができるし
>>> Question.objects.get(id=1)
<Question: How Are You?>
>>> Question.objects.get(id=0)
...
polls.models.Question.DoesNotExist: Question matching query does not exist.
>>> Question.objects.get(pk=1)
<Question: How Are You?>
id, primary key で指定して呼び出すこともできる
Top comments (0)