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