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

# 概要
DjangoのORMに`values`、`values_list`があります。また、それにつなげて使うことができる`first`や`distinct`もあり、どれがどんな型（クエリセット？リスト？タプル？）を返すのか等、それらのパターンを一通りまとめてみました。

## サンプルコード

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

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710373/d1d5b083-9fef-170e-69b7-0e7e5c5e4e5a.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`

```py
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`

```py
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`

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

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

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

### `filter` & `values`

```py
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`の値を持つ辞書のリストを取得します。

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

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

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

### `filter` & `values` & `first`

```py
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`

```py
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`

```py
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`

```py
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`

```py
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`

```py
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`

```py
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`することもできます。