55
Django Tutorial Part2 -- Model から Table を作って shell mode で Table の中身を動かす
前回の記事で Docker Compose で環境構築して
Django Tutorial の最初までやった
今回はその続きをやる
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)
Question とそれに関連する Choice のデータベースを作る
これ Blitz のチュートリアルでも見たぞ
これを読み込むためには 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',
を追加する
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 から migrate する
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
初期化の準備ファイルが作られた
migrate をする
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 を発行する
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
反映された
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 []>
作った投票アプリのモデルから、質問と選択肢を持ってきて
全部を引っ張ってくると、何も入っていない
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)>]>
しかしこれだと中身が出てこないので、
もう少し工夫する必要がある
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 の中身を見る時に、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 で指定して呼び出すこともできる
>>> 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)
のようにつけると追加できる!
>>> q.choice_set.count()
1
.count で数を数えられて
>>> 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日経っていない投稿かを判断する
admin を作る
55