LoginSignup
1
1

【Django】ORMのvalues/values_list/flat=Trueなどの出力結果を11パターンのコードでまとめた

Posted at

概要

DjangoのORMにvaluesvalues_listがあります。また、それにつなげて使うことができるfirstdistinctもあり、どれがどんな型(クエリセット?リスト?タプル?)を返すのか等、それらのパターンを一通りまとめてみました。

サンプルコード

DBは以下のようになっている前提です。

image.png

以下のパターンのサンプルコードをまとめました。

  • all
  • values
  • first
  • filter & values
  • filter & values & first
  • values_list
  • filter & values_list
  • filter & values_list & flat
  • filter & values_list & first
  • filter & values_list & first & flat
  • values_list & distinct

all

def all_only():
    response = Response.objects.all()
    print(response)
    print(response[0])

all_only()

# <QuerySet [<Response: Response object (test00000001)>, <Response: Response object (test00000002)>]>
# Response object (test00000001)

objects.all()を使用して、すべてのオブジェクトを取得します。

values

def values_only():
    response = Response.objects.values()
    print(response)
    print(response[0])

values_only()

# 結果
# <QuerySet [{'request_id': 'test00000001', 'response_body': 'test用です', 'create_date': datetime.datetime(2023, 11, 9, 10, 28, 16, 351918, tzinfo=<UTC>), 'update_date': datetime.datetime(2023, 11, 9, 10, 28, 16, 363564, tzinfo=<UTC>)}, {'request_id': 'test00000002', 'response_body': 'test用です', 'create_date': datetime.datetime(2023, 11, 9, 10, 30, 22, 831750, tzinfo=<UTC>), 'update_date': datetime.datetime(2023, 11, 9, 10, 30, 22, 844235, tzinfo=<UTC>)}]>
# {'request_id': 'test00000001', 'response_body': 'test用です', 'create_date': datetime.datetime(2023, 11, 9, 10, 28, 16, 351918, tzinfo=<UTC>), 'update_date': datetime.datetime(2023, 11, 9, 10, 28, 16, 363564, tzinfo=<UTC>)}

Responseモデルのすべてのオブジェクトに対して、各オブジェクトのフィールドとその値を含む辞書のリストを取得します。

response = Response.objects.all().values()でも同じ結果が返ってきました。

first

def first_only():
    response = Response.objects.first()
    print(response)
    print(response.request_id)

first_only()
# 結果
# Response object (test00000001)
# test00000001

Responseモデルの最初のオブジェクトを取得します。

filter & values

def filter_values(request_id):
    response = Response.objects.filter(request_id=request_id).values('request_id', 'response_body')
    print(response)
    print(response[0]['response_body'])

filter_values("test00000001")

# 結果
# <QuerySet [{'request_id': 'test00000001', 'response_body': 'test用です'}]>
# test用です

request_idが指定された値と一致するResponseオブジェクトをフィルタリングし、その結果からrequest_idresponse_bodyの値を持つ辞書のリストを取得します。

順序が逆でも、クエリの結果は同じです。

response = Response.objects.values('request_id', 'response_body').filter(request_id=request_id)

でも同じ結果が返ってきました。

filter & values & first

def filter_values_first(response_body):
    response = Response.objects.filter(response_body=response_body).values('request_id').first()
    print(response)
    print(response['request_id'])

filter_values_first("test用です")

# 結果
# {'request_id': 'test00000001'}
# test00000001

response_bodyが指定された値と一致するResponseオブジェクトをフィルタリングし、その結果から最初のオブジェクトのrequest_idの値を取得します。

上記例だと、"test用です"というレコードは他にもありますが、そちらは取得されません。
「最初のオブジェクト」だけが取得されていますね。

values_list

def values_list_only():
    response = Response.objects.values_list('request_id')
    print(response)
    print(response[0][0])

values_list_only()

# 結果
# <QuerySet [('test00000001',), ('test00000002',)]>
# test00000001

Responseモデルのすべてのオブジェクトに対して、request_idの値のみをリストとして取得します。

values_listは、デフォルトではタプルの要素を返しているのがポイントですね。

filter & values_list

def filter_values_list(request_id):
    response = Response.objects.filter(request_id=request_id).values_list('request_id', 'response_body')
    print(response)
    print(response[0][1])

filter_values_list("test00000001")

# 結果
# <QuerySet [('test00000001', 'test用です')]>
# test用です

request_idが指定された値と一致するResponseオブジェクトをフィルタリングし、その結果からrequest_idresponse_bodyの値を持つタプルのリストを取得します。

filter & values_list & flat

def filter_values_list_flat(response_body):
    response = Response.objects.filter(response_body=response_body).values_list('request_id', flat=True)
    print(response)
    print(response[0])

filter_values_list_flat("test用です")

# 結果
# <QuerySet ['test00000001', 'test00000002']>
# test00000001

response_bodyが指定された値と一致するResponseオブジェクトをフィルタリングし、その結果からrequest_idの値だけをフラットなリストとして取得します。

このflatにより、タプルではなくリストになっていることがわかります。

filter & values_list&first

def filter_values_list_first(response_body):
    response = Response.objects.filter(response_body=response_body).values_list('request_id').first()
    print(response)
    print(response[0])

filter_values_list_first("test用です")

# 結果
# ('test00000001',)
# test00000001

response_bodyが指定された値と一致するResponseオブジェクトをフィルタリングし、その結果から最初のオブジェクトのrequest_idの値をタプルとして取得します。

filter & values_list & first & flat

def filter_values_list_flat_first(response_body):
    response = Response.objects.filter(response_body=response_body).values_list('request_id', flat=True).first()
    print(response)

filter_values_list_flat_first("test用です")

# 結果
# test00000001

response_bodyが指定された値と一致するResponseオブジェクトをフィルタリングし、その結果から最初のオブジェクトのrequest_idの値をフラットなリストとして取得します。

values_list & distinct

def values_list_distinct():
    response = Response.objects.values_list('response_body').distinct()
    print(response)
    print(response[0][0])

values_list_distinct()

# 結果
# <QuerySet [('test用です',)]>
# test用です

Responseモデルのすべてのオブジェクトに対して、response_bodyの値を取得し、その結果から重複を除いた値のリストを取得します。

distinctは、データベースクエリの結果から重複した値を除外するためのメソッドです。
上記コードの場合、distinct()がないと<QuerySet [('test用です',), ('test用です',)]>というような結果が返されます(=重複するレコードも返される)。filterで条件指定して抽出したものをdistinctすることもできます。

1
1
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
1
1