Skip to content

Django:モデル・データ参照方法まとめ

はじめに

Djangoのこちらの公式ドキュメントから、テーブル・モデルを作成後にモデル内のデータ取得、及びモデル間でデータを参照する方法をまとめていきます。


テーブル・モデル

出版社(SyuppanSya)、著者(Tyosya)、本(Hon)のテーブルが存在することを想定して考えていきます。

モデル間の関係は、以下の通りです。
本と出版社の関係は、多対一。 Hon(多) --> (一)SyuppanSya
本と著者の関係は、多対対。Hon(多) --> (多)Tyosya


テーブル・モデル・コード

実際のデータ・モデルのコードは以下の通りです。

from django.db import models

class SyuppanSya(models.Model):
    name = models.CharField(max_length=100)
    tagline = models.TextField()

    def __str__(self):
        return self.name

class Tyosya(models.Model):
    name = models.CharField(max_length=200)
    email = models.EmailField()

    def __str__(self):
        return self.name

class Hon(models.Model):
    syuppan = models.ForeignKey(SyuppanSya, on_delete=models.CASCADE)
    title = models.CharField(max_length=255)
    body_text = models.TextField()
    pub_date = models.DateField()
    mod_date = models.DateField()
    authors = models.ManyToManyField(Author)
    number_of_comments = models.IntegerField()
    number_of_pingbacks = models.IntegerField()
    rating = models.IntegerField()

    def __str__(self):
        return self.title


テーブルデータの取得

  • 本テーブルに入っている全件を取得します。
    Hon.objects.all()

  • 本テーブルに入っている中で、本の題名が「噂のドラえもん」になっているものを取得します。
    Hon.objects.filter(title="噂のドラえもん")

  • 本テーブルに入っている中で、本の題名に「Theドラえもん」を含んでいるもの(大文字・小文字の区別あり)を取得します。
    Hon.objects.filter(title__contains="Theドラえもん")

  • 本テーブルに入っている中で、本の題名に「Theドラえもん」を含んでいるもの(大文字・小文字の区別なし)を取得します。
    Hon.objects.filter(title__icontains="Theドラえもん")

  • 本テーブルに入っている中で、本の題名が「Theドラえもん」で始まるもの(大文字・小文字の区別あり)を取得します。
    Hon.objects.filter(title__startswith="ドラえもん")

  • 本テーブルに入っている中で、本の題名が「Theドラえもん」で始まるもの(大文字・小文字の区別なし)を取得します。
    Hon.objects.filter(title__istartswith="ドラえもん")

  • 本テーブルに入っている中で、本の題名が「Theドラえもん」で終わるもの(大文字・小文字の区別あり)を取得します。
    Hon.objects.filter(title__endswith="ドラえもん")

  • 本テーブルに入っている中で、本の題名が「Theドラえもん」で終わるもの(大文字・小文字の区別なし)を取得します。
    Hon.objects.filter(title__iendswith="ドラえもん")

  • 本テーブルに入っている内で、出版年が2006年のものを取得します。
    Hon.objects.filter(pub_date__year=2006)


テーブル間の参照方法

  • 本テーブルから、出版社テーブル内の出版社名(name)を参照(順参照)。
    Hon.objects.filter(syuppan__name='Syppannsya_Syamei')

  • 出版社テーブルから、本テーブル内のタイトル(title)が「ドラえもん」であるものを参照(逆参照)。
    SyuppanSya.objects.filter(hon__title='ドラえもん')

  • 出版社テーブルから、本テーブル内のタイトル(title)に「ドラえもん」を含むものを参照(逆参照)。
    SyuppanSya.objects.filter(hon__title__contains='ドラえもん')

  • 出版社テーブルのidが1であるデータから、本テーブル内のデータを逆参照する。

    b = SyuppanSya.objects.get(id=1)
    b.hon_set.all()
  • 出版社テーブルのidが1であるデータから、本テーブル内のデータでタイトル(title)に「ドラえもん」を含むものを逆参照する。

    b = SyuppanSya.objects.get(id=1)
    b.hon_set.filter(title__contains='ドラえもん')


その他

  • 本テーブル内から、コメント数(number_of_comments)のほうがリンク数(number_of_pingbacks)よりも多いものを取得する。

    from django.db.models import F
    Entry.objects.filter(number_of_comments__gt=F('number_of_pingbacks'))
  • DBへのSQL発行回数(クエリ回数)について(悪い例)
    下記では、本テーブルの内容が2回呼び出されており、DBへのアクセスが結果として増えている。

    print([h.title for h in Hon.objects.all()])
    print([h.pub_date for h in Hon.objects.all()])
  • DBへのSQL発行回数(クエリ回数)について(良い例)
    下記では、本テーブルの内容を呼び出す回数が上記のコードに比べ1回に減った。

    queryset = title.objects.all()
    print([h.title for h in Hon.objects.all()])
    print([h.pub_date for h in Hon.objects.all()])


参考

https://docs.djangoproject.com/en/3.1/topics/db/queries/
https://docs.djangoproject.com/en/3.1/ref/models/querysets/