☆☆ 新着記事 ☆☆

2018年11月9日金曜日

Python Flaskは難しい randomのリストが答えわせ

Pythonで3択問題を作ったり、リストをランダムに表示する為のチュートリアルは結構ありますが、ほとんどが、IDLEなどのコマンドラインで実施して、「はい、できました!」って終わってる。

それって、でもすごく簡単。 なぜなら、回答の入力がinputコマンドでできてしまうから。

難しいのは、FlaskなどのWebフレーム・ワークを使ってブラウザを介してデータのやりとりをする場合。

課題は、
1) randomで生成したリストを答え合わせの関数に引き継げないので、正誤判断ができない。
2) 一問づつ問題を出して、つど解答してもらい、正誤記録を保持することが難しい。

Javascriptしかやった事がないけど、こんな問題は起こらなかった。 なかなか初心者にPythonは難しい。

以下が、問題のアウトプット。
問題を表示する関数で参照しているリストと、回答の答え合わせに使うリストが違ってしまっている。




以下が問題のコード

**Sample2.py

from flask import Flask, render_template, request, redirect, url_for
import csv, random
app = Flask(__name__)
# randomの生成
def rando():
    quiz = []
    quiz2 = []
    rand_quiz =[]
   
    with open("sampleTest.csv","r", encoding='utf-8_sig') as f:
        reader = csv.reader(f)
        listreader=list(reader)

        for i in range(0,len(listreader)):
            if listreader[i][0]=='ALL':
                for j in range(1,6):
                    quiz.append(listreader[i][j])
                quiz2.append(quiz)
                quiz=[]
    rand_quiz=random.sample(quiz2,len(quiz2))
    return rand_quiz
# ここからウェブアプリケーション用のルーティングを記述
# index にアクセスしたときの処理
@app.route('/')
def index():
    message=rando()
 
    # index.html をレンダリングする
    return render_template('index2.html',message=message)
@app.route('/ans', methods=['POST','GET'])
def ans():
    message2=rando()
   
  
    if request.method =='POST':
        answer = int(request.form['answer'])
        if answer == message2[0][4]:
            result = "Correct"
        else:
            result = "Wrong"
    else:
        result = 'Not Valid'
    return render_template("sample02.html",result=result,message2=message2)

if __name__ == '__main__':
    app.debug = True # デバッグモード有効化
    app.run(host='0.0.0.0') # どこからでもアクセス可能に

**index2.html

{% extends "layout.html" %}
{% block content %}
 
<div class="form">
{{message}}
<hr>
{% set i=0 %}
 <p>第{{ i+1 }}問目</p>
 <p>問題: {{message[i][0]}}</p>
 <p>選択肢</p>
 1.{{message[i][1]}} 2.{{message[i][2]}} 3.{{message[i][3]}}
 <form action="/ans" method="post">
    <label for="name">回答</label>
    <input type="text" id="answer" name="answer" placeholder="1">
    <button type="submit" class="btn btn-default">回答する</button>
    </form>
</div>
{% endblock %}


**sample02.html

<html>
<head>
 <meta charset="utf-8">
</head>
<body>
 {{result}}
 <hr>
 {{message2}}
</body>
</html>


と思ったけど、、、複数の戻り値のうち、別の関数では、1つだけを参照する方法を
発見した。
詳細は、Python 関数 引数と戻り値,変数の引き渡しを中心に

このやり方だと、

以下のようなコードが書ける。 これをFlask対応にすれば上手くいくはず!!

import csv, random
def index():
    # randomの生成
    quiz = []
    quiz2 = []
    rand_quiz =[]
   
    with open("sampleTest.csv","r", encoding='utf-8_sig') as f:
        reader = csv.reader(f)
        listreader=list(reader)
        for i in range(0,len(listreader)):
            if listreader[i][0]=='ALL':
                for j in range(1,6):
                    quiz.append(listreader[i][j])
                quiz2.append(quiz)
                quiz=[]
    rand_quiz=random.sample(quiz2,len(quiz2))
    print(rand_quiz)
   
    return quiz2 , rand_quiz
index()
return_value =index()
random_quiz = return_value[1]
print(random_quiz)

def ans():
    print(random_quiz)
ans()

Output
 
 
 
なんとか、これで答え合わせが出来ました!!
 
from flask import Flask, render_template, request, redirect, url_for
import csv, random
app = Flask(__name__)
 
# randomの生成
def rand():
    quiz = []
    quiz2 = []
    rand_quiz =[]
   
    with open("sampleTest.csv","r", encoding='utf-8_sig') as f:
        reader = csv.reader(f)
        listreader=list(reader)
        for i in range(0,len(listreader)):
            if listreader[i][0]=='ALL':
                for j in range(1,6):
                    quiz.append(listreader[i][j])
                quiz2.append(quiz)
                quiz=[]
    rand_quiz=random.sample(quiz2,len(quiz2))
    return rand_quiz
 
return_value = rand() #ここでグローバル変数にするのがコツ
 
# ここからウェブアプリケーション用のルーティングを記述
# index にアクセスしたときの処理
@app.route('/')
def index():
    rand_quiz = return_value
     
    # index.html をレンダリングする
  
    return render_template('index2.html',rand_quiz=rand_quiz)
# render_templateはNone Typeなので、戻り値が格納されていない。
♯ AttributeError: 'NoneType' object has no attribute 'app' となって、複数の戻り値をもって、
#一つだけ次の関数に引き渡すということができない。
 
@app.route('/ans', methods=['POST','GET'])
def ans():
   
    message2=return_value
  
    if request.method =='POST':
        answer = request.form['answer']
        if answer == message2[0][4]:
            result = "Correct"
        else:
            result = "Wrong"
    else:
        result = 'Not Valid'
    return render_template("sample02.html",result=result,message2=message2)

if __name__ == '__main__':
    app.debug = True # デバッグモード有効化
    app.run(host='0.0.0.0') # どこからでもアクセス可能に
 
ようやく、randomで生成したリストから出題し、答え合わせが出来るようになった!!
 

* が、ルートの外でrandomのリストを生成すると、ページがリフレッシュされただけでは、
    random生成の関数(上ではdef rand():)がCallされず、リストが変わらない。 
    これも意図したものではないが、かえって好都合かもしれない。。。??

          それにしても難しい。  

0 件のコメント:

コメントを投稿