Django チュートリアル Part2 -- モデルからテーブルを作ってシェルモードでテーブルの中身を移動


前回



前回の記事で Docker Compose で環境構築して

Django チュートリアルの最初までやった

今回はその続きをやる

パート2



https://docs.djangoproject.com/en/4.0/intro/tutorial02/

モデルを作る



https://docs.djangoproject.com/en/4.0/intro/tutorial02/#creating-models

docker-compose run web python manage.py migrate


これでDBの初期化をする必要がある

次に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)


質問とそれに関連する 選択肢のデータベースを作る

これ Blitz のルールでも見たぞ

モデルを読み込んで有効化する



https://docs.djangoproject.com/en/4.0/intro/tutorial02/#activating-models

これを入力するためには settings.py に書き込む必要がある

INSTALLED_APPS = [
    'polls.apps.PollsConfig',
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
]


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.



docker-compose run web \
python manage.py makemigrations polls


polls から移行する

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


初期化の準備ファイルができた

sqlmigrate で makemigrations で作った init ファイルを



移行する

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


これを実行して

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


反映された

シェルでモードでテーブルの中身を確認する



https://docs.djangoproject.com/en/4.0/intro/tutorial02/#playing-with-the-api

docker-compose run web \
python manage.py 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)
>>> 


少なくともモードになる

>>> from polls.models import Choice, Question

Question.objects.all()
<QuerySet []>


作った投票アプリのモデルから、質問と選択肢を持ってきて

全部を引っ張ってくると、何も入っていない

timezone の形でデータを入れて、保存して Question.object.all で中身を見る。




from django.utils import timezone


timezone のライブラリを持ってきて

q = Question(question_text="What's new?", pub_date=timezone.now())


qという一時現在変数に質問文のテキストと、作成日の日付にの日付を入れる

>>> q
<Question: Question object (None)>
>>> q.question_text
"What's new?"

>>> q.id
>>>


中身のカラムを指定するとみれる、今はidがないが

>>> q.save()
>>> q.id
1


保存するとidが出る

q.pub_date
datetime.datetime(2021, 12, 19, 13, 17, 26, 609289, tzinfo=<UTC>)


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.save()
>>> Question.objects.all()
<QuerySet [<Question: Question object (1)>]>


しかしこれだと中身が出てこないので、
もう少し工夫する必要がある

str を追加して text の中身を見えるようにする



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)
>>> Question.objects.all()
Traceback (most recent call last):
  File "<console>", line 1, in <module>
NameError: name 'Question' is not defined
>>> from polls.models import Choice, Question
>>> Question.objects.all()
<QuerySet [<Question: How Are You?>]>

質問の中身を見る時に、オブジェクトの中身のテキストが表示されるようになった

条件で求める



>>> 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?>]>

フィルター、で始まる、

で検索することができるし

>>> 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 で指定することもできる

Question id 1 下に .create(column='hoge') でChoice を作る




>>> q = Question.objects.get(pk=1)
>>> q.choice_set.all()
<QuerySet []>


子供テーブルは parent.children_set.all() で見れるらしい.

>>> q.choice_set.create(choice_text='Not much', votes=0)
<Choice: Not much>
>>> q.choice_set.all()
<QuerySet [<Choice: Not much>]>


今後 .create(column_name='text', column_name2=0)のようにつけると追加できる!

.count() で数える




>>> q.choice_set.count()
1


.count で数を数えられて

.delete() で削除する




>>> c = q.choice_set.filter(choice_text__startswith='Not')
>>> c
<QuerySet [<Choice: Not much>]>
>>> c.delete
<bound method QuerySet.delete of <QuerySet [<Choice: Not much>]>>
>>> c.delete()
(1, {'polls.Choice': 1})
>>> q.choice_set.all()
<QuerySet []>
>>> 


取得して .delete() 投入と削除できた!

最近投稿されたかどうかの関数を作る




    def was_published_recently(self):
        return self.pub_date >= timezone.now() - datetime.timedelta(days=1)


現時点から1日経っていない投稿かを判断する

これからやること



https://docs.djangoproject.com/en/4.0/intro/tutorial02/#introducing-the-django-admin

admin を作る