LoginSignup
0
0

More than 3 years have passed since last update.

ManytoMany fieldの使い方講座

Last updated at Posted at 2021-03-22

今日やること
・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テーブルのa1publications(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>]>
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0