今日やること
・manytomany fieldをドキュメント使って学習したのでその時のメモ
今回使うテーブルは以下の通りである。
# learn manytomany field
class Publication(models.Model):
title = models.CharField(max_length=30)
class Meta:
ordering = ['title']
def __str__(self):
return self.title
class Article(models.Model):
headline = models.CharField(max_length=100)
publications = models.ManyToManyField(Publication)
class Meta:
ordering = ['headline']
def __str__(self):
return self.headline
では、Publicationテーブルのレコードを追加してみましょう。
In [1]: from core.models import Publication, Article
In [2]: p1 = Publication(title='The Python Journal')
In [3]: p1.save()
In [4]: p2 = Publication(title='Science News')
In [5]: p2.save()
In [6]: p3 = Publication(title='Science Weekly')
In [7]: p3.save()
次にArticleテーブルにレコードを追加していこう。
In [8]: a1 = Article(headline='Django lets you build Web apps easily')
この時、a1
を保存する前にPublicationとの関連づけをすることはできない
このようなエラーが出てしまう。なので、a1
を保存してから関連付をしよう。
>>> a1.publications.add(p1)
Traceback (most recent call last):
...
ValueError: "<Article: Django lets you build Web apps easily>" needs to have a value for field "id" before this many-to-many relationship can be used.
↓
# save it!!
>>> a1.save()
Associate the Article with a Publication:
>>> a1.publications.add(p1)
これでArticleテーブルのa1
にpublications(Publicationテーブル)
を関連付けることができた。
どんどん進めていこう!
In [14]: a2 = Article(headline='NASA uses Python')
In [15]: a2.save()
In [16]: a2.publications.add(p1,p2)
In [17]: a2.publications.add(p3)
In [18]: a2.publications.add(p3)
17, 18番目でp3
を2回追加しているが複数回同じものを関連付をすることも可能である。
次にcreate()
を使ってArticleにPublicationを追加していこう。
new_publication = a2.publications.create(title='Highlights for Children')
これでa2
に関連付けたpublicationにtitle='Highlights for Children'
を追加することができた。
Articleオブジェクトは関連したPublicationオブジェクトにアクセスすることができるのでその確認をしたい。
In [21]: a1.publications.all()
Out[21]: <QuerySet [<Publication: The Python Journal>]>
In [22]: a2.publications.all()
Out[22]: <QuerySet [<Publication: Highlights for Children>, <Publication: Science News>, <Publication: Science Weekly>, <Publication: The Python Journal>]>
Publicationオブジェクトは関連したArticleオブジェクトにアクセスすることができる。
In [23]: p2.article_set.all()
Out[23]: <QuerySet [<Article: NASA uses Python>]>
In [24]: p1.article_set.all()
Out[24]: <QuerySet [<Article: Django lets you build Web apps easily>, <Article: NASA uses Python>]>
次にフィルタリングを使って取得したいquerysetを取得しよう。
In [21]:
# Publicationオブジェクトのidを使って取得
Article.objects.filter(publications__id=1)
Out[21]: <QuerySet [<Article: Django lets you build Web apps easily>, <Article: NASA uses Python>]>
In [22]:
# pk(主キー)を使って取得
Article.objects.filter(publications__pk=1)
Out[22]: <QuerySet [<Article: Django lets you build Web apps easily>, <Article: NASA uses Python>]>
In [23]:
# 21、22と同様
Article.objects.filter(publications=1)
Out[23]: <QuerySet [<Article: Django lets you build Web apps easily>, <Article: NASA uses Python>]>
In [24]:
# publicationsのtitle(絡む)が`Science`で始まるものを取得 Article.objects.filter(publications__title__startswith="Science"
...: )
Out[24]: <QuerySet [<Article: Django lets you build Web apps easily>, <Article: NASA uses Python>, <Article: NASA uses Python>, <Article: NASA uses Python>]>
In [25]:
# p1と連携しているArticleを取得
Article.objects.filter(publications=p1)
Out[25]: <QuerySet [<Article: Django lets you build Web apps easily>]>
In [26]:
# distinct()・・・重複を除去してデータを取得する
Article.objects.filter(publications__title__startswith="Science"
...: ).distinct()
Out[26]: <QuerySet [<Article: Django lets you build Web apps easily>, <Article: NASA uses Python>, <Article: NASA uses Python>]>
In [27]:
# count()・・・数を数える
Article.objects.filter(publications__title__startswith="Science"
...: ).count()
Out[27]: 4
In [35]:
`NASA`で始まるものを取得
Publication.objects.filter(article__headline__startswith="NASA")
...:
Out[35]: <QuerySet [<Publication: Highlights for Children>, <Publication: Highlights for Children>, <Publication: Science News>, <Publication: Science Weekly>, <Publication: Science Weekly>, <Publication: The Python Journal>]>
In [36]: Publication.objects.filter(id=1)
Out[36]: <QuerySet [<Publication: The Python Journal>]>
In [37]: Publication.objects.filter(pk=1)
Out[37]: <QuerySet [<Publication: The Python Journal>]>
In [38]: Publication.objects.filter(article__headline__startswith="NASA")
...:
Out[38]: <QuerySet [<Publication: Highlights for Children>, <Publication: Highlights for Children>, <Publication: Science News>, <Publication: Science Weekly>, <Publication: Science Weekly>, <Publication: The Python Journal>]>
In [39]: Publication.objects.filter(article__id=1)
Out[39]: <QuerySet [<Publication: The Python Journal>]>
In [40]: Publication.objects.filter(article__pk=1)
Out[40]: <QuerySet [<Publication: The Python Journal>]>
In [41]: Publication.objects.filter(article=1)
Out[41]: <QuerySet [<Publication: The Python Journal>]>
In [42]: Publication.objects.filter(article=a1)
Out[42]: <QuerySet [<Publication: Science News>, <Publication: The Python Journal>]>
In [43]: Publication.objects.filter(article__in=[1,2]).distinct()
Out[43]: <QuerySet [<Publication: Highlights for Children>, <Publication: Science News>, <Publication: Science Weekly>, <Publication: The Python Journal>]>
In [44]: Publication.objects.filter(article__in=[a1,a2]).distinct()
Out[44]: <QuerySet [<Publication: Highlights for Children>, <Publication: Science News>, <Publication: Science Weekly>, <Publication: The Python Journal>]>
In [46]:
# 指定した照合パラメタに一致 しない オブジェクトの集合を表現する
Article.objects.exclude(publications=p2)
Out[46]: <QuerySet [<Article: Django lets you build Web apps easily>, <Article: NASA uses Python>, <Article: NASA uses Python>]>