Diese Präsentation wurde erfolgreich gemeldet.
Wir verwenden Ihre LinkedIn Profilangaben und Informationen zu Ihren Aktivitäten, um Anzeigen zu personalisieren und Ihnen relevantere Inhalte anzuzeigen. Sie können Ihre Anzeigeneinstellungen jederzeit ändern.

DjangoのORMことはじめ

2.781 Aufrufe

Veröffentlicht am

DjangoのORMことはじめ 2018.01.27 SQLアンチパターン読書会スペシャル

Veröffentlicht in: Internet
  • Loggen Sie sich ein, um Kommentare anzuzeigen.

DjangoのORMことはじめ

  1. 1. DjangoのORMことはじめ 2018.01.27 読書会スペシャル 於 GEEKLAB.NAGANO
  2. 2. 自己紹介 にしざわこういち twitter: @koty GEEKLAB.NAGANO 管理人見習い SIer(Javaとか.NETとか)→現職(Python/Django/AWS/Vue.js)
  3. 3. Django概要 ● Pythonで作られたフルスタック・フレームワーク ● ORM - Object Relational Mapping オブジェクト関係マッピング が優れている。 ● 管理サイトが素晴らしい。 ● 学習コストが低い  引用元:Python Django入門 (1) - Qiita これに加え「DB Migrationが便利」                     参考:普段Django を使っている人間がruby on railsを勉強してみた話 - slideshare
  4. 4. DjangoのORMことはじめ SQLアンチパターン 読書会スペシャルということで、 DjangoのORM周辺の話をします
  5. 5. 目次 ● Model ● Query ○ select ○ insert ○ update ○ delete ○ 外部キー先のデータの取得 ● DB Migration
  6. 6. Model from django.db import models class Tag(models.Model): url = models.CharField(max_length=100) class User(models.Model): username = models.CharField(max_length=100) class Profile(models.Model): tags = models.ManyToManyField(Tag, related_name='profiles') user = models.ForeignKey(User, unique=True, related_name='profile') 多対多 1対1 primary_key=True を指定しない場合は、 idという列ができる
  7. 7. select 単純な全件select users = User.objects.all().order_by(‘username’) # select id, username from user order by username; 単純な条件 users2 = User.objects.filter(username='koty') # select id, username from user where username='koty';
  8. 8. select ユニークキーでの取得 try: koty = User.objects.get(id=1) except User.DoesNotExist: pass except User.MultipleObjectsReturned: pass 0件のときは例外が発生 2件以上のときも例外が発生
  9. 9. select あいまい検索 users3 = User.objects.filter(username__startswith='koty') # select id, username from user where username like 'koty%'; users4 = User.objects.filter(username__endswith='koty') # select id, username from user where username like '%koty'; users5 = User.objects.filter(username__contains='koty') # select id, username from user where username like '%koty%';
  10. 10. select group by from django.db.models import Count Tag.objects.values('url') .annotate(url_count=Count('url')) .filter(url_count__gt=1) # select url count(username) as url_count from tag group by url having count(url)>1
  11. 11. insert koty2 = User.objects.create(username='koty2') # insert into user ('username') values ('koty2') koty2 = User(username='koty2') koty2.save() # insert into user ('username') values ('koty2')
  12. 12. update と delete koty2.username = 'koty3' koty2.save() # update user set username='koty3' where id=2 koty2.delete() # delete from user where id=2;
  13. 13. 外部キー先のデータの取得 p = Profile.objects.get(id=1) u = p.user profiles = Profile.objects.all() for p in profiles: print(p.user) profiles = Profile.objects.select_related('user').all() # select profile.id, profile.user_id, user.id, user.username from user inner join user on profile.user_id=user.id 参照された時点で select が走る N+1 問題 select_relatedでフィールドを指定すると JOINになる
  14. 14. 外部キー先のデータの取得 逆方向の参照 profiles = user.profile.all() profile = profiles[0] user = models.OneToOneField(User, related_name='profile') profile = user.profile OneToOneフィールドで定義すれば単一オブジェクトを取得で きる
  15. 15. 外部キー先のデータの取得 逆方向参照でのN+1問題への対応 users = User.objects.prefetch_related('profile').all() # select id, user_id from profile where id user_id in (1, 2); prefetch_relatedで事前に取得しておける
  16. 16. ナマSQL Person.objects.raw('SELECT id, first_name, last_name, birth_date FROM myapp_person') ナマSQLも書けるが、得体の知れない負けた感 https://docs.djangoproject.com/en/2.0/topics/db/sql/
  17. 17. ログ出力 LOGGING = { 'version': 1, 'disable_existing_loggers': False, 'handlers': { 'console': { 'level': 'DEBUG', 'class': 'logging.StreamHandler', }, }, 'loggers': { 'django.db.backends': { 'handlers': ['console'], 'level': 'DEBUG', }, }, } どんなSQLが発行されるか、普段の開発から注意を 払っておく
  18. 18. DB Migration modelにフィールドを追加 class User(models.Model): username = models.CharField(max_length=100) birthday = models.DateField(null=True) > ./manage.py makemigrations > ./manage.py migrate migrationファイルが生成される migration適用。alter table が走る ←フィールドを追加
  19. 19. おしまい Djangoはいいぞ

×