見出し画像

【サンプルコード付き】Django モデル オブジェクトの取得方法-基礎編-

モデル設定したけど、views.pyでどのようにデータを呼び出すかよくわからない……

本日はこのようなお悩みを解決するためにモデルで設定した内容をどのようにviews.pyで呼び出すか(※オブジェクト取得方法)について解説していきます。※"クエリ取得"と表現されることもあります。

なおオブジェクト取得方法は、ボリュームが多いため基礎編と応用編の2回に分けて解説していきます。今回は基礎編です。

まだモデルについて理解が不十分と感じる方は、"3. モデル関連記事"も確認してみてください。

では、本題に入ります。

1. 単体オブジェクトを取得

単体オブジェクトを取得する場合はget()メソッドを使います。

解説の前に以下のモデル前提とします。

models.py

from django.db import models
from django.contrib.auth.models import User

class Post(models.Model):
   title = models.CharField(max_length=255)
   author = models.ForeignKey(User, on_delete=models.CASCADE)
   body = models.TextField()
  
   def __str__(self):
       return self.title

views.pyで具体的にどのようにオブジェクトを取得するか解説していきます。

下記のようにモデルで設定したフィールド情報からオブジェクトを取得することができます。

>>>Post.objects.get(title='タイトル')
<Post: タイトル>

またpk(「id」でもOK)でもオブジェクト情報を取得できます。

>>> Post.objects.get(pk=1)
<Post: テスト>​

get()メソッドは単体オブジェクトを取得するための方法ですので複数オブジェクトが検出される場合エラーとなります。

>>> author = User.objects.get(username='saito')
>>> Post.objects.get(author=author)

#エラーメッセージ
MultipleObjectsReturned: get() returned more than one Post -- it returned 2!

もちろんオブジェクトが見つからない場合はエラーとなります。

>>> Post.objects.get(pk=100)
DoesNotExist: Post matching query does not exist.

2. 複数オブジェクトを取得

複数オブジェクト取得のためのall()、filter()メソッドを解説していきます。

また今回も以下のモデル前提とします。

models.py

from django.db import models
from django.contrib.auth.models import User

class Post(models.Model):
    title = models.CharField(max_length=255)
    author = models.ForeignKey(User, on_delete=models.CASCADE)
    body = models.TextField()
    price = models.PositiveIntegerField(blank=True, null=True)

 def __str__(self):
     return self.title

2.1 all()メソッド

全てのオブジェクトを取得するためにはall()メソッドを使用します。

>>> Post.objects.all()
<QuerySet [<Post: テスト>, <Post: how to study django>, <Post: タイトル>, <Post: タイトル2>]>

上記のようにQuerySetという形で、一連のデータが入ったリストを取得することができます。なおall()メソッドの場合、getメソッド()とは異なりオブジェクトが存在しなくてもエラーとはならず、以下のように空のリストを返します。

>>> Post.objects.all()
<QuerySet []> #オブジェクト存在しない場合

2.2 filter()メソッド

filter()メソッドは検索条件をつけて複数オブジェクトを取得するためのメソッドです。

>>> author = User.objects.get(username='saito')
>>> Post.objects.filter(author=author)
<QuerySet [<Post: テスト>, <Post: how to study django>]>

上記のように投稿者によって検索条件をつけてオブジェクトリストを取得する時にfilter()メソッドを使います。今回は著者名(ユーザー名)'saito'の情報をもとに検索しています。

具体的な検索条件について以降で解説していきます。

2.2.1 AND条件

>>> author = User.objects.get(username='saito')
>>> Post.objects.filter(title='テスト', author=author) 
<QuerySet [<Post: テスト>]>​

上記のようにfilter(A, B)とすることでA and Bの条件で検索することがきます。

2.2.2 OR条件

>>> from django.db.models import Q #Qをインポート

>>> author = User.objects.get(username='shogsaito')
>>> Post.objects.filter(Q(title='テスト')|Q(author=author))
<QuerySet [<Post: テスト>, <Post: how to study django>]>

上記のようにfilter(Q(A) | Q(B))とすることでA or Bの条件で検索することができます。

2.2.3 不等号条件

>>> Post.objects.filter(price__gt=1000) # >1000 gtは「Greater Than」
>>> Post.objects.filter(price__lt=1000) # <1000 ltは「Less Than」
>>> Post.objects.filter(price__gte=1000) # >=1000 gteは「Greater Than or Equal」
>>> Post.objects.filter(price__lte=1000) # <=1000 lteは「Less Than or Equal」

上記のようにfilter(モデルフィールド__不等号条件=数値)不等号条件で検索できます。

2.2.4 文字列に関する条件

先ほどfilter(title='テスト'…)について紹介しましたが、こちらはタイトルが"テスト"に完全一致する場合のみオブジェクトを取得する条件になっています。

上記以外にもいくつか文字列に関する検索条件があるので解説していきます。

◆大文字小文字を区別しない一致

>>> Post.objects.filter(title='how to study django') #完全一致
<QuerySet [<Post: how to study django>]>
>>> Post.objects.filter(title__iexact='how to STUDY Django') #大文字小文字を区別なし
<QuerySet [<Post: how to study django>, <Post: HOW TO STUDY DJANGO>]>

モデルフィールド__iexactで大文字小文字を区別しない一致の条件で検索することができます。iexactの"i"は大文字小文字を区別しないという意味でよく使用されるので覚えておきましょう。

特定の文字列を"含む"

>>> Post.objects.filter(title__contains='how') #大文字小文字区別あり
<QuerySet [<Post: how to study django>]>
#DBがSQliteの場合、containsは大文字小文字区別しない↓ 
<QuerySet [<Post: how to study django>, <Post: HOW TO STUDY DJANGO>]>

>>> Post.objects.filter(title__icontains='how') #大文字小文字区別しない
<QuerySet [<Post: how to study django>, <Post: HOW TO STUDY DJANGO>]>

モデルフィールド__contains特定の文字列を含む条件で検索することができます。containsの場合は大文字小文字区別しますが、icontains区別しません。ただしDBがSQliteの場合containsは、icontainsと同様に大文字小文字区別しないのでご注意ください。

特定の文字列で"始まる/終わる"

>>> Post.objects.filter(title__startswith='ho') #~で始まる 大文字小文字区別あり
<QuerySet [<Post: how to study django>]>
#DBがSQliteの場合、startswithは大文字小文字区別しない↓ 
<QuerySet [<Post: how to study django>, <Post: HOW TO STUDY DJANGO>]>

>>> Post.objects.filter(title__endswith='go') #~で終わる 大文字小文字区別あり
<QuerySet [<Post: how to study django>]>
#DBがSQliteの場合、endswithは大文字小文字区別しない↓ 
<QuerySet [<Post: how to study django>, <Post: HOW TO STUDY DJANGO>]>

>>> Post.objects.filter(title__istartswith='ho') #~で始まる 大文字小文字区別なし
<QuerySet [<Post: how to study django>, <Post: HOW TO STUDY DJANGO>]>

>>> Post.objects.filter(title__iendswith='go') #~で終わる 大文字小文字区別なし
<QuerySet [<Post: how to study django>, <Post: HOW TO STUDY DJANGO>]>​

モデルフィールド__startswith(_endswith)〜で始まる(終わる)条件で検索することができます。startswith(endswith)の場合は大文字小文字区別しますが、istartswith(iendswith)区別しません。ただしDBがSQliteの場合startswith(endswith)は、istartswith(iendswith)と同様に大文字小文字区別しないのでご注意ください。

2.2.5 リレーション先のモデルより検索

リレーションでよく使われるフィールドは、「OneToOneField」「ForeignKey」「ManyToManyField」の3種です。これらフィールドが使用されている時、リレーション先のモデルを使って検索する場合がありますので方法について解説していきます。

検索方法解説する前に、もう一度前提のモデルを復習しましょう。

models.py

from django.db import models
from django.contrib.auth.models import User

class Post(models.Model):
    title = models.CharField(max_length=255)
    author = models.ForeignKey(User, on_delete=models.CASCADE)
    body = models.TextField()
    price = models.PositiveIntegerField(blank=True, null=True)

def __str__(self):
    return self.title

authorの部分がForeignKeyでUserモデルと紐付いていますUserモデルのフィールドは、「username」「email」等のフィールドが設定されているのでこれらの情報を使いながら検索する方法について解説していきます。

>>> Post.objects.filter(author__username='saito')
<QuerySet [<Post: タイトル>, <Post: タイトル2>, <Post: HOW TO STUDY DJANGO>]>

>>> author = User.objects.get(username='saito')
>>> Post.objects.filter(author_id=author.id) #author_id→author__idでも可
<QuerySet [<Post: タイトル>, <Post: タイトル2>, <Post: HOW TO STUDY DJANGO>]>

>>> author = User.objects.get(username='saito')
>>> Post.objects.filter(author=author.id)
<QuerySet [<Post: タイトル>, <Post: タイトル2>, <Post: HOW TO STUDY DJANGO>]>

>>> author = User.objects.get(username='saito')
>>> Post.objects.filter(author=author)
<QuerySet [<Post: タイトル>, <Post: タイトル2>, <Post: HOW TO STUDY DJANGO>]>

上記のように複数のパターンで検索することができます。(結果は全て同じ)

モデルフィールド__リレーション先モデルフィールドモデルフィールド_id(__idでも可)、モデルフィールド=〇〇.id等の形式で検索することができます。

サンプルコードにいくつかのパターンを紹介しましたのでお好みに合わせてお使いください。

3. モデル記事参考

まだモデルについて理解が不十分と感じる方は、以下の記事も併せてお読みください。

4. shellについて

オブジェクトを確認する簡単に確認する手法として、djangoのshellを使うととても便利です。一々views.py、templateファイル、urls.pyを設定せずともオブジェクトを確認することができるのでぜひマスターしましょう。

一度公式ブログ↓を読んでみることをオススメします。

5. 最後に

いかがでしたか。

今回は、設定したモデルよりオブジェクトを取得する方法について解説しました。

views.pyを設定する上でかなり高頻度で使用する内容になりますので、ぜひマスターしましょう。

次回は、応用編として少しマニアックだけど便利なメソッドについて解説しますので、ぜひお楽しみに!



この記事が気に入ったらサポートをしてみませんか?