Pythonの一つのキーに複数の値を含む辞書型の取り出しに悩んだ

## 概要
質問フォームから入力したデータをバックエンドのPythonに送信して受け取る。
受け取ったデータはDBに格納するなど。
質問は複数あり、同様に回答も複数ある。

## 結論
辞書型の取り出しには、get(),getlist()を使う

## コード
### 1.フロントから入力したデータを送信

```javascript
const url = 'https://xxxxxx.xxx/regist'
const params = new FormData();
            
params.append("id", this.id);
params.append("category", this.category);
for(let i=0;i<this.questions.length;i++){
    params.append("question", this.questions[i]);
    params.append("answers", this.answers[i]);
}
            
const headers = {
    accept: "application/json",
    "Content-Type": "multipart/form-data",
    Authorization: `Bearer ` + API_TOKEN
};
            
const response = await axios.post(url, params, { headers: headers })
if(response.status == '200'){
    // 成功した時の処理   
}
else{
    // 失敗した時の処理
}
```

:::note info
補足
:::

```javascript
for(let i=0;i<this.questions.length;i++){
    params.append("question", this.questions[i]);
    params.append("answers", this.answers[i]);
}
```
appendで値を追加した場合、既存のキーが存在する場合には値のセットに新しい値を追加します。
その為、一つのキーに複数の要素を含めることができます。

逆に、同じキーが存在する場合に上書きしたい場合は、set()を利用すると上書きされます。
```javascript
params.set("question", this.questions[i]);
```



### 2.バックエンド側のPythonで受信
（確認として出力のみ）

```python
class lineQuestionnaireApi(APIView):

    def post(self, request, format=None):
        print(request.data)
        question_data = request.data
        
        print(question_data['id'])
        print(question_data['category'])
        print(question_data['question'])
        print(question_data['answers'])
```

### 実行結果

```python
<QueryDict: {
'id': ['abc123'], 
'category': ['2'], 
'question': ['好きな色？', '好きな食べ物？', '好きな数字？', '好きな季節？'], 
'answers': ['青', 'いちご', '７', '春']
}>


abc123　    #id
2         #category
好きな季節？ #question
# 質問の最後のみしか出力されていない
# 期待していた結果→['好きな色？', '好きな食べ物？', '好きな数字？', '好きな季節？']
春        #answers
# 回答の最後のみしか出力されていない
# 期待していた結果→['青', 'いちご', '７', '春']
```

## 疑問
questionとanswersの値が最後の要素だけしか出力されない

## おさらい
### リスト型

要素の書き換え可
index番号で要素にアクセス

```python
list_data = ['a', 'b', 'c', 'd']
print(list_data[0])

### a
```
### タプル型

要素の書き換え不可
index番号で要素にアクセス

```python
tuple_data = ('a', 'b', 'c', 'd')
print(list_data[0])

### a
```

### 辞書型

要素の書き換え不可
キー（文字列や数値）で要素にアクセス

```python
dict_data = {'い':'a', 'ろ':'b', 'は':'c', 'に':'d'}
print(list_data['い'])

### a
```



## 試したこと

### 受け取ったデータ型を確認してみる

```python
question_data = request.data
print(type(question_data))
```

```
<class 'django.http.request.QueryDict'>
```

QueryDict型になっている。
辞書型の拡張ということらしい。

### 辞書型の値の取り出し
DjangoのQueryDictには同じキーの中にある複数の値をlistとして取り出せるメソッドがある。
それが、**getlist**
ということで、getlistを使って値を取り出す。

```python
user_id = questionnaire_data.get('user_id', default=None)
category = questionnaire_data.get('category', default=None)
question_list = questionnaire_data.getlist('question', default=None)
answers_list = questionnaire_data.getlist('answers', default=None)
```

:::note info
リスト型以外は以下でも値は取得できるが、辞書型オブジェクトから取得する場合はget()メソッドを使う

user_id = questionnaire_data['user_id']

辞書型オブジェクト.get(key, default=None)
（keyが存在しなかった場合にNoneを返す）
:::

```python
print(question_list)
# ['好きな色？', '好きな食べ物？', '好きな数字？', '好きな季節？']
```

list型として取り出すことに成功。

### リスト型からインデックスと要素取得して順番に取り出す

続いて、リストの値を順番に取り出す。
今回は、質問と回答をセットで取り出したいので、共通となるインデックス番号をキーとする。

インデックスと要素を取得したいので、
enumerate関数を利用。

```python
print(user_id)
print(category)
for key,value in enumerate(question_list):
    print(question_list[key])
    print(answers_list[key])
```

出力結果

```python
abc123　      #id
2           #category
# -----　以下はfor文で出力した内容 -----
好きな色？     #question[0]
青          #answers[0]
好きな食べ物？ #question[1]
いちご       #answers[1]
好きな数字？  #question[2]
7          #answers[2]
好きな季節？  #question[3]
春         #answers[3]
```

想定していた結果を得ることができました。

## 所感
pythonでよく使うリストと辞書型の理解があいまいのままだった点と
フロントから受け取ったデータ型の理解が漏れていた点が悩んだ理由。