2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

記事投稿キャンペーン 「2024年!初アウトプットをしよう」

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

Posted at

概要

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

結論

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

コード

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

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{
    // 失敗した時の処理
}

補足

for(let i=0;i<this.questions.length;i++){
    params.append("question", this.questions[i]);
    params.append("answers", this.answers[i]);
}

appendで値を追加した場合、既存のキーが存在する場合には値のセットに新しい値を追加します。
その為、一つのキーに複数の要素を含めることができます。

逆に、同じキーが存在する場合に上書きしたい場合は、set()を利用すると上書きされます。

params.set("question", this.questions[i]);

2.バックエンド側の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'])

実行結果

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


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

疑問

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

おさらい

リスト型

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

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

### a

タプル型

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

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

### a

辞書型

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

dict_data = {'':'a', '':'b', '':'c', '':'d'}
print(list_data[''])

### a

試したこと

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

question_data = request.data
print(type(question_data))
<class 'django.http.request.QueryDict'>

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

辞書型の値の取り出し

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

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)

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

user_id = questionnaire_data['user_id']

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

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

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

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

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

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

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

出力結果

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

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

所感

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

2
0
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
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?