Djangoのチュートリアルに従ったPollアプリにdjongoパッケージを使用してMongoDBを導入してみます。
コードはGithub上にあります。
https://github.com/Yosuke-Nishizawa/django-x-mongodb
目次
環境
Python 3.8.5
MongoDB shell version v4.4.2
Django 3.0.5
Pollアプリのベース作成
プロジェクト・アプリの作成
# 仮想環境作成
python -m venv venv
# 仮想環境適用
source venv/bin/activate
# djangoインストール
pip install django
# mysiteプロジェクト作成
django-admin startproject mysite
# pollsアプリを作成
cd mysite
python manage.py startapp polls
pollsアプリをプロジェクトに含める
mysite/settings.py
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'polls.apps.PollsConfig',
]
モデル定義
polls/models.py
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)
djongo導入
インストール
pip install djongo
DB接続情報修正
mysite/settings.py
DATABASES = {
'default': {
'ENGINE': 'djongo',
'NAME': 'poll',
'CLIENT': {
'host': 'localhost',
}
}
}
DBマイグレーション
python manage.py makemigrations polls
Migrations for 'polls':
polls/migrations/0001_initial.py
- Create model Question
- Create model Choice
python manage.py migrate
Operations to perform:
Apply all migrations: admin, auth, contenttypes, polls, sessions
Running migrations:
This version of djongo does not support "NULL, NOT NULL column validation check" fully. Visit https://www.patreon.com/nesdis
Applying contenttypes.0001_initial...This version of djongo does not support "schema validation using CONSTRAINT" fully. Visit https://www.patreon.com/nesdis
OK
Applying auth.0001_initial...This version of djongo does not support "schema validation using KEY" fully. Visit https://www.patreon.com/nesdis
This version of djongo does not support "schema validation using REFERENCES" fully. Visit https://www.patreon.com/nesdis
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...This version of djongo does not support "COLUMN DROP NOT NULL " fully. Visit https://www.patreon.com/nesdis
This version of djongo does not support "DROP CASCADE" fully. Visit https://www.patreon.com/nesdis
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 polls.0001_initial... OK
Applying sessions.0001_initial... OK
DBの確認
mongo
> show dbs
pollが作成されている
poll 0.000GB
> use poll
> whos collections
Question
, Choice
に対するcollectionが作成されている
__schema__
auth_group
auth_group_permissions
auth_permission
auth_user
auth_user_groups
auth_user_user_permissions
django_admin_log
django_content_type
django_migrations
django_session
polls_choice
polls_question
モデルを通してデータをやり取りしてみる
わかりやすいように__str__
を定義しておきます。
polls/models.py
from django.db import models
class Question(models.Model):
question_text = models.CharField(max_length=200)
pub_date = models.DateTimeField('date published')
def __str__(self):
return str(self.__dict__)
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 str(self.__dict__)
単純にinsert
from polls.models import Question
from django.utils import timezone
# Questionにデータ設定
q1 = Question(question_text='質問1', pub_date=timezone.now())
q1.save()
q2 = Question(question_text='質問2', pub_date=timezone.now())
q2.save()
q3 = Question(question_text='質問3', pub_date=timezone.now())
q3.save()
# Questionの内容確認
for q in Question.objects.all():
print(q)
{'_state': <django.db.models.base.ModelState object at 0x7ff7e06389a0>, 'id': 1, 'question_text': '質問1', 'pub_date': datetime.datetime(2020, 12, 1, 5, 46, 54, 680000, tzinfo=<UTC>)}
{'_state': <django.db.models.base.ModelState object at 0x7ff7e0638ee0>, 'id': 2, 'question_text': '質問2', 'pub_date': datetime.datetime(2020, 12, 1, 5, 46, 54, 725000, tzinfo=<UTC>)}
{'_state': <django.db.models.base.ModelState object at 0x7ff7e0638ca0>, 'id': 3, 'question_text': '質問3', 'pub_date': datetime.datetime(2020, 12, 1, 5, 46, 54, 734000, tzinfo=<UTC>)}
外部キーを張ったテーブルにinsert
from polls.models import Choice, Question
# Question取得
q = Question.objects.get(id=1)
print(f'Question id=1 : {q}')
# Choiceデータ設定
q.choice_set.create(choice_text='選択肢1', votes=0)
q.choice_set.create(choice_text='選択肢2', votes=1)
q.choice_set.create(choice_text='選択肢3', votes=2)
# 確認
for c in q.choice_set.all():
print(c)
Question id=1 : {'_state': <django.db.models.base.ModelState object at 0x7f80fefec2e0>, 'id': 1, 'question_text': '質問1', 'pub_date': datetime.datetime(2020, 12, 1, 5, 46, 54, 680000, tzinfo=<UTC>)}
{'_state': <django.db.models.base.ModelState object at 0x7f80ff008e80>, 'id': 1, 'question_id': 1, 'choice_text': '選択肢1', 'votes': 0}
{'_state': <django.db.models.base.ModelState object at 0x7f80ff008f10>, 'id': 2, 'question_id': 1, 'choice_text': '選択肢2', 'votes': 1}
{'_state': <django.db.models.base.ModelState object at 0x7f80ff008d00>, 'id': 3, 'question_id': 1, 'choice_text': '選択肢3', 'votes': 2}
MongoDBでデータの内容を確認
mongo
> use poll
> db.polls_question.find()
{ "_id" : ObjectId("5fc5d8ce6626f3a8c904db3c"), "id" : 1, "question_text" : "質問1", "pub_date" : ISODate("2020-12-01T05:46:54.680Z") }
{ "_id" : ObjectId("5fc5d8ce6626f3a8c904db3d"), "id" : 2, "question_text" : "質問2", "pub_date" : ISODate("2020-12-01T05:46:54.725Z") }
{ "_id" : ObjectId("5fc5d8ce6626f3a8c904db3e"), "id" : 3, "question_text" : "質問3", "pub_date" : ISODate("2020-12-01T05:46:54.734Z") }
> db.polls_choice.find()
{ "_id" : ObjectId("5fc5dd5759846395af0570be"), "id" : 1, "question_id" : 1, "choice_text" : "選択肢1", "votes" : 0 }
{ "_id" : ObjectId("5fc5dd5759846395af0570bf"), "id" : 2, "question_id" : 1, "choice_text" : "選択肢2", "votes" : 1 }
{ "_id" : ObjectId("5fc5dd5759846395af0570c0"), "id" : 3, "question_id" : 1, "choice_text" : "選択肢3", "votes" : 2 }