LoginSignup
281
299

More than 3 years have passed since last update.

Django逆引きチートシート(QuerySet編)

Last updated at Posted at 2019-06-11

コード例に出てくるProductOrderOrderDetailはモデルクラス

検索系

全てのレコードを取得したい

products = Product.objects.all()

主キーを指定してレコードを取得したい

主キーのカラム名がなんであってもpk=で検索できる

product = Product.objects.get(pk=1)

取得条件を指定してレコードを取得したい

products = Product.objects.filter(name="hoge")

取得条件を複数(AND)指定してレコードを取得したい

カンマ区切りで複数かくとANDになる

products = Product.objects.filter(name="hoge", size="L")

取得条件を複数(IN)指定してレコードを取得したい

<カラム名>=の代わりに<カラム名>__in=とする

products = Product.objects.filter(name__in=["hoge", "fuga"])

取得条件を複数(OR)指定してレコードを取得したい

Q(<条件>)で一つの条件が生成できる。この式を|で繋ぐとORになる。

from django.db.models import Q

products = Product.objects.filter(Q(name="hoge") | Q(name__startswith="foo"))
# -> name='hoge' OR name LIKE 'foo%'

大小比較の取得条件でレコードを取得したい

# weight > 2
products = Product.objects.filter(weight__gt=2)
# weight < 2
products = Product.objects.filter(weight__lt=2)
# weight >= 2
products = Product.objects.filter(weight__gte=2)
# weight <= 2
products = Product.objects.filter(weight__lte=2)

範囲条件でレコードを取得したい

# 4から12まで
# (weight BETWEEN 4 AND 12)
products = Product.objects.filter(weight__range=(4, 12))

SQLのIS NULL(またはIS NOT NULL)検索をしたい

# size IS NULL
products = Product.objects.filter(size__isnull=True)
# size IS NOT NULL
products = Product.objects.filter(size__isnull=False)

前方一致(LIKE)でレコードを取得したい

<カラム名>=の代わりに<カラム名>__startswith=とする

products = Product.objects.filter(name__startswith="ho")

中間一致(LIKE)でレコードを取得したい

<カラム名>=の代わりに<カラム名>__contains=とする

products = Product.objects.filter(name__contains="ho")

後方一致(LIKE)でレコードを取得したい

<カラム名>=の代わりに<カラム名>__endswith=とする

products = Product.objects.filter(name__endswith="ho")

昇順でソートして取得したい

nameの昇順

products = Product.objects.order_by("name")

filter()がある場合はfilter()の後に続けて書く

降順でソートして取得したい

nameの降順

products = Product.objects.order_by("-name")

filter()がある場合はfilter()の後に続けて書く

重複除去(SELECT DISTINCT)して取得したい

products = Product.objects.distinct("name", "created_on")

filter()がある場合はfilter()の後に続けて書く

辞書型として取得したい

products = Product.objects.values()

filter()がある場合はfilter()の後に続けて書く

特定のカラムの値のリストとして取得したい

sizes = Product.objects.values_list("size", flat=True)
# flat=Trueがないとタプルのリストになる

filter()がある場合はfilter()の後に続けて書く

結合(JOIN)して取得したい

select_related(<関連オブジェクト名>)を使用する

orders = Order.objects.select_related("order_detail").all()

悲観ロックをしたい

select_for_update()を使用する

products = Products.objects.select_for_update().filter(name__startswith="hoge")

with transaction.atomic():
    # 通常はトランザクション内部でしかロックは意味を持たない
    for product in products:
       # productの更新処理など

ノンブロッキング処理を行いたい場合はnowait=Trueを引数に追加する

レコードの件数を数えたい

product_count = Product.objects.count()

filter()がある場合はfilter()の後に続けて書く

合計を求めたい

from django.db.models import Sum

obj = Product.objects.aggregate(total_price=Sum("price"))
# -> obj = {"total_price": 24000}

filter()がある場合はfilter()の後に続けて書く

最新(最古)のレコードを取得したい

# 最新
latest_order = Order.objects.latest("created_on")
# 最古
earliest_order = Order.objects.earliest("created_on")

filter()がある場合はfilter()の後に続けて書く

最初(最後)のレコードを取得したい

# 最初
first_order = Order.objects.order_by("id").first()
# 最後
last_order = Order.objects.order_by("id").last()

filter()がある場合はfilter()の後に続けて書く

レコードの存在チェックをしたい

ifの条件に直接書く場合、

if Product.objects.filter(name="hoge").exists():
    # name="hoge"のレコードがある場合、ここに入る

変数に代入する場合、

e = Product.objects.filter(name="hoge").exists()
# eにはTrueかFalseが入る

更新系

レコードを挿入したい

Product.objects.create(name="hoge", price=1200, size="M")

または、

product = Product(name="hoge", price=1200, size="M")
product.save()

レコードがあれば取得、なければ挿入したい

product, created = Product.objects.get_or_create(
  name="hoge", 
  price=1200
  defaults={size="S"}
)
  • name="hoge"かつprice=1200のレコードがあれば取得して変数productに代入する。変数createdはFalseになる。
  • name="hoge"かつprice=1200のレコードがなければname="hoge", price=1200, size="S"のレコードを作成し変数productに代入する。変数createdはTrueになる。

レコードがあれば更新、なければ挿入したい

product, created = Product.objects.update_or_create(
  name="hoge", 
  price=1200
  defaults={size="S"}
)
  • name="hoge"かつprice=1200のレコードがあれば、size="S"に更新して変数productに代入する。変数createdはFalseになる。
  • name="hoge"かつprice=1200のレコードがなければname="hoge", price=1200, size="S"のレコードを作成し変数productに代入する。変数createdはTrueになる。

特定のレコードの特定のカラムを更新したい

product = Product.objects.get(pk=1) # 条件を設定してから
product.name = "new onion"          # 書き換えて
# ...書き換えるカラムは複数でも良い...
product.save()                      # 更新

条件にマッチするレコードを一括更新したい

products = Product.objects.filter(size="M") # 条件を設定してから
products.update(name="new onion")            # 一括更新

条件にマッチするレコードを一括削除したい

products = Product.objects.filter(size="M") # 条件を設定してから
products.delete()                           # 一括削除
281
299
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
281
299