概要
DjangoのORMにvalues
、values_list
があります。また、それにつなげて使うことができるfirst
やdistinct
もあり、どれがどんな型(クエリセット?リスト?タプル?)を返すのか等、それらのパターンを一通りまとめてみました。
サンプルコード
DBは以下のようになっている前提です。
以下のパターンのサンプルコードをまとめました。
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_id
とresponse_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_id
とresponse_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
することもできます。