Welche Datenstruktur für Multiple-Choice-Fragentrainer

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Sirius3
User
Beiträge: 17711
Registriert: Sonntag 21. Oktober 2012, 17:20

Ohne den dazugehörigen Code kann man mit der Fehlermeldung nichts anfangen.
Mit Raten kommt man beim Programmieren selten weiter.
Benutzeravatar
Dennis89
User
Beiträge: 1124
Registriert: Freitag 11. Dezember 2020, 15:13

Sorry, das ist der Code zur Meldung:

Code: Alles auswählen

 json import loads, dumps
from pathlib import Path
from random import sample

from flask import Flask, render_template, request
from werkzeug.exceptions import abort

QUESTIONS_PATH = Path("/home/dennis/Question_Trainer/questions.json")
QUESTIONS = loads(QUESTIONS_PATH.read_bytes())
app = Flask(__name__)


def number_of_questions():
    return [number for number, _ in enumerate(QUESTIONS)]


def get_question(question_id):
    return QUESTIONS[question_id]["question"]


def get_answers_in_random_order(question_id):
    return sample(QUESTIONS[question_id]["answers"], 4)


def get_right_answer(question_id, answer):
    return answer == QUESTIONS[question_id]["answers"][0]


@app.route("/question", methods=["GET", "POST"])
def chose_question():
    question_id = int(request.form["answer"]) - 1
    return render_template(
        "question.html",
        question=get_question(question_id),
        id=question_id,
        answers=get_answers_in_random_order(question_id),
    )


@app.route("/answer", methods=["GET", "POST"])
def check_answer():
    question_id = int(request.form["id"])
    answer = str(request.form["answer"])
    answers = request.form['answers']
    rating = "Richtig!" if get_right_answer(question_id, answer) else "Falsch!"
    return render_template(
        "question.html",
        question=get_question(question_id),
        id=question_id,
        answers=loads(answers), 
        rating=rating,
    )


@app.route("/next", methods=["GET", "POST"])
def next_question():
    try:
        question_id = int(request.form["id"])
        question = get_question(question_id)
        return render_template(
            "question.html",
            question=question,
            id=question_id,
            answers=get_answers_in_random_order(question_id),
        )
    except IndexError:
        return render_template("finish.html")


@app.route("/back", methods=["GET", "POST"])
def previous_question():
    question_id = int(request.form["id"])
    if question_id < 0:
        return index()
    question = get_question(question_id)
    return render_template(
        "question.html",
        question=question,
        id=question_id,
        answers=get_answers_in_random_order(question_id),
    )


@app.route("/")
def index():
    return render_template("index.html", questions=number_of_questions())
Grüße
Dennis
"When I got the music, I got a place to go" [Rancid, 1993]
Benutzeravatar
__blackjack__
User
Beiträge: 13004
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Wenn man die Daten da durch schleusen will, dann müssen die a) in Anführungszeichen stehen, b) als JSON serialisiert sein, und c) entsprechend escaped werden, weil Zeichen im JSON ja wieder eine besondere Bedeutung in HTML(-Attributen) haben können. Macht Jinja c) in Flask von sich aus, oder muss man das extra konfigurieren, beziehungsweise manuell immer den entsprechenden Filter auf die Daten anwenden?

Wegen der Normalisierung in HTML-Attributen finde ich das aber sowieso reichlich fragil. Auch bei den Eingabeelementen mit den Antworten. Da kann es für meinen Geschmack zu leicht passieren, dass das was vom Browser zurück kommt, subtil anders ist, als das was man hin geschickt hat.

Edit: Du hast ja auch zwei Fragen mit einer Grafik zusätzlich zum Text. Oder liessen die sich per Unicode-Zeichen abbilden?
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
Benutzeravatar
Dennis89
User
Beiträge: 1124
Registriert: Freitag 11. Dezember 2020, 15:13

In der HTML-Datei stehen jetzt Anführungszeichen, das habe ich gleich das nach deinem ersten Post dazu eingefügt:

Code: Alles auswählen

{% extends 'base.html' %}

<head>
    <meta charset="UTF-8">
    <link rel="stylesheet" href="{{ url_for('static', filename= 'css/style.css') }}">
    <title>Fragetrainer</title>
</head>

{% block content %}
    <h1>{% block title %} Wähle weise! {% endblock %}</h1>

    {{ question }}
    <form action="/answer" method="POST">
    <input type="hidden" name="id" value="{{ id }}">
    {% for answer in answers %}
    <p><input type="submit" name="answer" value="{{ answer }}"></p>
    {% endfor %}
 <input type="hidden" name="answers" value="{{ answers }}">

 </form>

{{ rating }}


	<form action="/back" method="POST">
        <input type="hidden" name="id" value="{{ id - 1 }}">
        <p><input type="submit" name="back" value="Zurück"></p>
        </form>

        <form action="/next" method="POST">
         <input type="hidden" name="id" value="{{ id + 1 }}">
        <p><input type="submit" name="next" value="Weiter"></p>
        </form>

{% endblock %}
Wegen b) habe ich vorhin angefangen zu versuchen die Antworten anstatt einer Liste, als JSON an den Server zu senden.
Zu c) kann ich gar nichts sagen.

Wenn das mit den Grafiken zu Problemen führt, würde ich die zwei Fragen einfach weg lassen. Die kann man dann auch so noch lernen.

Soll ich vielleicht den Punkt, dass die Antworten nochmals dargestellt werden einfach weglassen? Irgendwie hört sich das für mich reichlich kompliziert an. Nicht das ich faul bin, nur als Hobbyprogrammierer bin ich manchmal schneller als gewünscht an meinen Grenzen. 😒

Gute Nacht, bis morgen und vielen Dank noch mal an alle für eure Hilfe!
Dennis
"When I got the music, I got a place to go" [Rancid, 1993]
Benutzeravatar
sparrow
User
Beiträge: 4164
Registriert: Freitag 17. April 2009, 10:28

Ich würde dringend raten nicht die String-Repräsentation der Liste an die Seite zu übergeben sondern entsprechend json.
Dann würde ich mir mal anschauen, was da eigentlich in request.form['answers'] drin steht.

Und ansonsten gilt, was __blackjack__ gesagt hat: Quellcode der gerenderten Seite anschauen und gucken ob da richtig escaped ist.
Benutzeravatar
Dennis89
User
Beiträge: 1124
Registriert: Freitag 11. Dezember 2020, 15:13

Hallo und vielen Dank für die Antworten.

Das mit dem JSON an den Server senden hatte ich gestern versucht. Dann hat meine HTML-Seite keine Liste mehr und meine 'for'-Schleife iteriert über jedes Element der JSON-Zeichenkette und ich habe soviele Buttons wie die Zeichenkette Elemente hat. Dann haben wir gesagt, dass das mit der Liste so passt und jetzt verstehe ich euch so, dass ich die Liste doch als JSON senden muss. Verstehe ich euch richtig?
Muss ich die Liste an sich anders aufbauen, damit wenn die als JSON gesendet wird, über die Elemene (Wörter bzw. Antworten) iteriert werden kann und nicht über die einzelnen Zeichen, oder wie stelle ich das an?

Eure restlichen Hinweise kann ich erst heute Abend umsetzen und mit euch teilen.

Grüße
Dennis
"When I got the music, I got a place to go" [Rancid, 1993]
Sirius3
User
Beiträge: 17711
Registriert: Sonntag 21. Oktober 2012, 17:20

Du brauchst die Information über die Antworten in zwei Darstellungen. Erstens als Liste, um damit die Buttons zu erzeugen und zweitens als JSON-String, um die Information über die Reihenfolge jedesmal an den Server zurückschicken zu können.
Benutzeravatar
Dennis89
User
Beiträge: 1124
Registriert: Freitag 11. Dezember 2020, 15:13

Danke für die Antwort.
Was ich so halbauf dem SPrung noch kurz an Infos da lassen kann:

Code: Alles auswählen

@app.route("/question", methods=["GET", "POST"])
def chose_question():
    question_id = int(request.form["answer"]) - 1
    answers = get_answers_in_random_order(question_id)
    return render_template(
        "question.html",
        question=get_question(question_id),
        id=question_id,
        answers=answers,
        answers_json=dumps(answers)
    )


@app.route("/answer", methods=["GET", "POST"])
def check_answer():
    question_id = int(request.form["id"])
    answer = str(request.form["answer"])
    answers_json = request.json['answers_json']
    answers = loads(answers_json)
    rating = "Richtig!" if get_right_answer(question_id, answer) else "Falsch!"
    return render_template(
        "question.html",
        question=get_question(question_id),
        id=question_id,
        answers=answers, 
        answers_json=answers_json,
        rating=rating,
    )
Ich weis, das man keine Datentypen in Namen angibt, aber für den Versuch ist mir nichts anderes eingefallen.

Das ergibt diesen Seitenquelltext:

Code: Alles auswählen

<!doctype html>
<html lang="en">
  <head>
    <!-- Required meta tags -->
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">

    <!-- Bootstrap CSS -->
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">

    <title> Wähle weise! </title>
  </head>
  <body>
    <nav class="navbar navbar-expand-md navbar-light bg-light">
        <a class="navbar-brand" href="/">Fragenübersicht</a>
        <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
            <span class="navbar-toggler-icon"></span>
        </button>
    </nav>
    <div class="container">
        
    <h1> Wähle weise! </h1>
    
    Wie heißt du?
    <form action="/answer" method="POST">    
    <input type="hidden" name="id" value="0">
    
    <p><input type="submit" name="answer_json" value="Hans"></p>
    
    <p><input type="submit" name="answer_json" value="Karle"></p>
    
    <p><input type="submit" name="answer_json" value="Peter"></p>
    
    <p><input type="submit" name="answer_json" value="Hubert"></p>
    
 <input type="hidden" name="answers" value="[&#39;Hans&#39;, &#39;Karle&#39;, &#39;Peter&#39;, &#39;Hubert&#39;]">
   
 </form>




        <form action="/back" method="POST">  
        <input type="hidden" name="id" value="-1">
        <p><input type="submit" name="back" value="Zurück"></p>
        </form>
   
        <form action="/next" method="POST">
         <input type="hidden" name="id" value="1">
        <p><input type="submit" name="next" value="Weiter"></p>
        </form>


    </div>

    <!-- Optional JavaScript -->
    <!-- jQuery first, then Popper.js, then Bootstrap JS -->
    <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
  </body>
</html>
Ich gehe mal davon aus, dass die Zeichen in dem JSON-String falsch sind?
Muss jetzt gleich weiter, bin nachher wieder am PC, den ersten Versuch wollte ich euch aber denoch kurz da lassen.

Viele Grüße
Dennis
"When I got the music, I got a place to go" [Rancid, 1993]
Benutzeravatar
sparrow
User
Beiträge: 4164
Registriert: Freitag 17. April 2009, 10:28

Warum heißen denn die Buttons "answer_json"?

Ansonsten sieht das doch gut aus.
Benutzeravatar
Dennis89
User
Beiträge: 1124
Registriert: Freitag 11. Dezember 2020, 15:13

Weil ich neugierig, ungeduldig und unaufmerksam war. Ich wollte unbedingt 10 Minuten vor einer Onlinevorlesung das hier noch testen, weil es mich den ganzen Tag schon beschäftigt. Eigentlich habe ich schon oft gelernt, dass das Schnelle bei mir nicht funktioniert, aber naja.

Ich habe das getauscht, die Antworten haben wieder 'answer' aus der Liste und der hidden-input hat den json-String bekommen.
Das sieht dann jetzt so aus:

Code: Alles auswählen

<!doctype html>
<html lang="en">
  <head>
    <!-- Required meta tags -->
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">

    <!-- Bootstrap CSS -->
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">

    <title> Wähle weise! </title>
  </head>
  <body>
    <nav class="navbar navbar-expand-md navbar-light bg-light">
        <a class="navbar-brand" href="/">Fragenübersicht</a>
        <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
            <span class="navbar-toggler-icon"></span>
        </button>
    </nav>
    <div class="container">
        
    <h1> Wähle weise! </h1>
    
    Wie heißt du?
    <form action="/answer" method="POST">    
    <input type="hidden" name="id" value="0">
    
    <p><input type="submit" name="answer" value="Peter"></p>
    
    <p><input type="submit" name="answer" value="Hubert"></p>
    
    <p><input type="submit" name="answer" value="Karle"></p>
    
    <p><input type="submit" name="answer" value="Hans"></p>
    
 <input type="hidden" name="answers_json" value="[&#39;Peter&#39;, &#39;Hubert&#39;, &#39;Karle&#39;, &#39;Hans&#39;]">
   
 </form>




        <form action="/back" method="POST">  
        <input type="hidden" name="id" value="-1">
        <p><input type="submit" name="back" value="Zurück"></p>
        </form>
   
        <form action="/next" method="POST">
         <input type="hidden" name="id" value="1">
        <p><input type="submit" name="next" value="Weiter"></p>
        </form>


    </div>

    <!-- Optional JavaScript -->
    <!-- jQuery first, then Popper.js, then Bootstrap JS -->
    <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
  </body>
</html>
Ist &#39; jetzt ein Problem oder ist das "normal" und ist wie in @__blackjack__ 's Erklärung auf den Browser zurück zuführen oder ist das ein "Json-Ding" und hängt mit den Escape-Zeichen zusammen?

Er sagt mir aber auch:
"Did not attempt to load JSON data because the request Content-Type was not 'application/json'."

Und was wir durch 'answers_json = request.json['answers_json']' verursacht. Dabei habe ich das doch jetzt als JSON übergeben.

Vielen Dank und Grüße
Dennis

Edit: Der Code ist noch wie zwei Posts weiter oben.
"When I got the music, I got a place to go" [Rancid, 1993]
Benutzeravatar
sparrow
User
Beiträge: 4164
Registriert: Freitag 17. April 2009, 10:28

Wieso denn request.json()?
Du hast ein Formular. Das beinhaltet Elemente. Auf die greifst du doch mit request.form[] zu. Und du hast ein weiteres, verstecktes Element hinzugefügt. Warum sollte man da dann mit .json dran kommen? Wo in der Dokumentation steht das?

Du musst den Wert des Elements lesen und _das_ ist das ist eine Zeichenkette und muss mit json.loads() geparst werden.
Benutzeravatar
__blackjack__
User
Beiträge: 13004
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Dennis89: "&#39;" ist ein einfaches Anführungszeichen in HTML als ”Entity” kodiert. Was dann aber falsch ist, weil das Python ist und kein JSON. JSON fasst Zeichenketten in doppelte Anführungszeichen ein, das heisst die Liste wurde nicht als JSON kodiert. Was nicht automatisch passiert, das muss man selbst explizit machen. Doppelte Anführungszeichen sind "&#34;" als HTML-Entity.

`request.json()` liefert JSON wenn die gesamte Antwort tatsächlich aus einem JSON-Wert besteht. Das tun Forms nicht. Weiss jetzt aus dem FF gar nicht ob das überhaupt ohne JavaScript vom Browser aus geht. Das macht man üblicherweise über AJAX/fetch-API-Aufrufe von JavaScript aus.
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
Benutzeravatar
Dennis89
User
Beiträge: 1124
Registriert: Freitag 11. Dezember 2020, 15:13

Das habe ich falsch verstanden, ich dachte, wenn ich json will, dann muss ich nutzen. Weil da steht "If the mimetype is application/json this will contain the parsed JSON data.". Da habe ich mich zu sehr auf "parsed JSON data" konzentriert und nicht gesehen, dass das nicht funktioniert, wie ich dachte.

Jetzt habe ich zwar die Daten, aber die sind für 'loads' nicht in Ordnung:

Code: Alles auswählen

Traceback (most recent call last):
  File "/home/dennis/questions_trainer/lib64/python3.11/site-packages/flask/app.py", line 2548, in __call__
    return self.wsgi_app(environ, start_response)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/dennis/questions_trainer/lib64/python3.11/site-packages/flask/app.py", line 2528, in wsgi_app
    response = self.handle_exception(e)
               ^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/dennis/questions_trainer/lib64/python3.11/site-packages/flask/app.py", line 2525, in wsgi_app
    response = self.full_dispatch_request()
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/dennis/questions_trainer/lib64/python3.11/site-packages/flask/app.py", line 1822, in full_dispatch_request
    rv = self.handle_user_exception(e)
         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/dennis/questions_trainer/lib64/python3.11/site-packages/flask/app.py", line 1820, in full_dispatch_request
    rv = self.dispatch_request()
         ^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/dennis/questions_trainer/lib64/python3.11/site-packages/flask/app.py", line 1796, in dispatch_request
    return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/dennis/Question_Trainer/app.py", line 47, in check_answer
    answers = loads(answers_json)
              ^^^^^^^^^^^^^^^^^^^
  File "/usr/lib64/python3.11/json/__init__.py", line 346, in loads
    return _default_decoder.decode(s)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib64/python3.11/json/decoder.py", line 337, in decode
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib64/python3.11/json/decoder.py", line 355, in raw_decode
    raise JSONDecodeError("Expecting value", s, err.value) from None
json.decoder.JSONDecodeError: Expecting value: line 1 column 2 (char 1)
127.0.0.1 - - [06/Feb/2023 22:52:15] "GET /answer?__debugger__=yes&cmd=resource&f=style.css HTTP/1.1" 304 -
127.0.0.1 - - [06/Feb/2023 22:52:15] "GET /answer?__debugger__=yes&cmd=resource&f=debugger.js HTTP/1.1" 304 -
127.0.0.1 - - [06/Feb/2023 22:52:15] "GET /answer?__debugger__=yes&cmd=resource&f=console.png HTTP/1.1" 304 -
der Code dazu:

Code: Alles auswählen

@app.route("/answer", methods=["GET", "POST"])
def check_answer():
    question_id = int(request.form["id"])
    answer = str(request.form["answer"])
    answers_json = request.form['answers_json']
    answers = loads(answers_json)
    rating = "Richtig!" if get_right_answer(question_id, answer) else "Falsch!"
    return render_template(
        "question.html",
        question=get_question(question_id),
        id=question_id,
        answers=answers, 
        answers_json=answers_json,
        rating=rating,
    )
Der Inhalt von 'answers_json' ist:

Code: Alles auswählen

['Peter', 'Hubert', 'Hans', 'Karle']
'answers_json' habe ich mir in eine Datei schreiben lassen, allerdings mit encoding 'UTF-8' wird dabei was verschluckt/geändert? Sollte ich da etwas anderes angeben um die "wirklichen" Daten zu sehen, falls das nicht die wirklichen sind? Ohne encoding kommt das selbe Ergebnis raus. Hm naja das ist wieder mal nur geraten.

Also eigentlich sollte doch alles gut sein. Ich hab das mal in der Python-Console getestet, das funktioniert wie gewünscht:

Code: Alles auswählen

>>>answers = ['Peter', 'Hubert', 'Hans', 'Karle']
>>>answers_json = json.dumps(answers)
>>>for element in answers_json:
>>>    print(element)
    
[
"
P
e
t
e
r
"
,
 
"
H
u
b
e
r
t
"
,
 
"
H
a
n
s
"
,
 
"
K
a
r
l
e
"
]
>>>for element in json.loads(answers_json):
>>>    print(element)
    
Peter
Hubert
Hans
Karle[/codeø

Danke, gute Nacht und Grüße
Dennis

Gerade vor dem Absende sehe ich erst die Nachricht von __blackjack__.
Dir auch danke für die Erklärung. Ich habe im Code doch 'json.dumps' benutzt und dachte damit hätte ich das nach json codiert?
"When I got the music, I got a place to go" [Rancid, 1993]
Sirius3
User
Beiträge: 17711
Registriert: Sonntag 21. Oktober 2012, 17:20

Offensichtlich benutzt Du im Template immer noch ›value="{{ answers }}"‹ statt ›value="{{ answers_json }}"‹
Benutzeravatar
sparrow
User
Beiträge: 4164
Registriert: Freitag 17. April 2009, 10:28

__blackjack__ hat weiter oben bereits geschriebenen, dass es in JSON Zeichenketten nicht in einfache Anführungszeichen eingeschlossen werden. Das ist auch der Unterschied in deinem letzten Post.

Daher auch Sirius3s Folgerung.
Oder du benutzt noch immer die String-Darstellung der Liste und nicht json.dumps()
Benutzeravatar
Dennis89
User
Beiträge: 1124
Registriert: Freitag 11. Dezember 2020, 15:13

Guten Morgen,

ich werde verrückt, es funktioniert!
Bin gerade nicht zu Hause, habe aber auch eine Ubuntu Maschine hier und dann Code aus dem Forum genommen, noch einmal eure Antworten durchgegangen und den Code angepasst und jetzt läuft es. 😍

Tausend Dank euch allen für die Hilfe und das es euch nicht zu dumm geworden ist!

questions.json

Code: Alles auswählen

[
    {"question": "Wie heißt du?", "answers": ["Hans", "Peter", "Hubert","Karle"]},
    {"question": "Was machst du morgen?", "answers": ["Arbeiten", "Essen", "Sport", "Schlafen"]}
  ]
app.py

Code: Alles auswählen

from json import loads, dumps
from pathlib import Path
from random import sample

from flask import Flask, render_template, request
from werkzeug.exceptions import abort

QUESTIONS_PATH = Path("/home/dennis/Dokumente/test/questions.json")
QUESTIONS = loads(QUESTIONS_PATH.read_bytes())
app = Flask(__name__)


def number_of_questions():
    return [number for number, _ in enumerate(QUESTIONS)]


def get_question(question_id):
    return QUESTIONS[question_id]["question"]


def get_answers_in_random_order(question_id):
    return sample(QUESTIONS[question_id]["answers"], 4)


def get_right_answer(question_id, answer):
    return answer == QUESTIONS[question_id]["answers"][0]


@app.route("/question", methods=["GET", "POST"])
def chose_question():
    question_id = int(request.form["answer"]) - 1
    answers = get_answers_in_random_order(question_id)
    return render_template(
        "question.html",
        question=get_question(question_id),
        id=question_id,
        answers=answers,
        answers_json=dumps(answers)
    )


@app.route("/answer", methods=["GET", "POST"])
def check_answer():
    question_id = int(request.form["id"])
    answer = str(request.form["answer"])
    answers_json = request.form['answers_json']
    answers = loads(answers_json)
    rating = "Richtig!" if get_right_answer(question_id, answer) else "Falsch!"
    return render_template(
        "question.html",
        question=get_question(question_id),
        id=question_id,
        answers=answers,
        answers_json=answers_json,
        rating=rating,
    )


@app.route("/next", methods=["GET", "POST"])
def next_question():
    try:
        question_id = int(request.form["id"])
        question = get_question(question_id)
        return render_template(
            "question.html",
            question=question,
            id=question_id,
            answers=get_answers_in_random_order(question_id),
        )
    except IndexError:
        return render_template("finish.html")


@app.route("/back", methods=["GET", "POST"])
def previous_question():
    question_id = int(request.form["id"])
    if question_id < 0:
        return index()
    question = get_question(question_id)
    return render_template(
        "question.html",
        question=question,
        id=question_id,
        answers=get_answers_in_random_order(question_id),
    )


@app.route("/")
def index():
    return render_template("index.html", questions=number_of_questions())
question.html

Code: Alles auswählen

{% extends 'base.html' %}

<head>
    <meta charset="UTF-8">
    <link rel="stylesheet" href="{{ url_for('static', filename= 'css/style.css') }}">
    <title>Fragetrainer</title>
</head>

{% block content %}
    <h1>{% block title %} Wähle weise! {% endblock %}</h1>

    {{ question }}
    <form action="/answer" method="POST">
        <input type="hidden" name="id" value="{{ id }}">
        {% for answer in answers %}
            <p><input type="submit" name="answer" value="{{ answer }}"></p>
        {% endfor %}
        <input type="hidden" name="answers_json" value="{{ answers_json }}">

    </form>

{{ rating }}


    <form action="/back" method="POST">
        <input type="hidden" name="id" value="{{ id - 1 }}">
        <p><input type="submit" name="back" value="Zurück"></p>
    </form>

    <form action="/next" method="POST">
        <input type="hidden" name="id" value="{{ id + 1 }}">
        <p><input type="submit" name="next" value="Weiter"></p>
    </form>

{% endblock %}
Einen schöneren Namen für 'answers_json' muss ich noch finden und jetzt kann ich mich noch an die style.css machen, damit die Buttons nebeneinander sind oder gibt es davor noch eine wichtigere Baustelle?

Vielen Dank und Grüße
Dennis
"When I got the music, I got a place to go" [Rancid, 1993]
Benutzeravatar
__blackjack__
User
Beiträge: 13004
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Soweit ich mich erinnere gibt es einen Template-Filter für JSON in Jinja.
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
Benutzeravatar
Dennis89
User
Beiträge: 1124
Registriert: Freitag 11. Dezember 2020, 15:13

Ja da habe ich was gefunden. In wie fern würde mir das helfen?

Ist von der Logik her noch irgendwas nicht sauber? Also abgesehen davon das man vielleicht tricksen könnte beim antworten, aber das ist hier für uns nicht relevant, es wird auch nichts ausgewertet oder ähnliches.

Danke und Grüße
Dennis
"When I got the music, I got a place to go" [Rancid, 1993]
Benutzeravatar
Dennis89
User
Beiträge: 1124
Registriert: Freitag 11. Dezember 2020, 15:13

Guten Morgen,

ich hole dieses Thema noch einmal raus, weil mir bei diesem Projekt noch etwas eingefallen ist.

Als ich auf meinem Laptop daran gearbeitet habe, habe ich dieses mal eine Entwicklungsumgebung mit 'venv' gebaut unter anderem auch das ich mit 'flask run' immer wieder mein Fortschritt testen konnte.
Meistens habe ich nur PyCharm genutzt, dass baut die Umgebung ja bei erstellen eines Projekts selbstständig. Aber es ist für meine Frage eigentlich egal, in welcher Umgebung ich gearbeitet habe.

Wie sollte das eigentlich im produktiven Zustand sein? Hätte ich auf meinem V-Server, auf dem das gerade läuft, auch eine Entwicklungsumgebung erstellen sollen in der das läuft?
Weil jetzt habe ich zum Beispiel Flask systemweit installiert. Ich habe neulich was davon gehört, dass man so Sachen eher isoliert laufen lässt. Aber leider habe ich das nur am Rande mitbekommen, deswegen die Frage an euch.

Wie würde man das einrichten?

Als Server für die Webseite nutze ich Uvicorn, da bei 'flask run' die Meldung kam, das man es nur zum testen nutzen soll.


Danke und Grüße
Dennis
"When I got the music, I got a place to go" [Rancid, 1993]
Benutzeravatar
Dennis89
User
Beiträge: 1124
Registriert: Freitag 11. Dezember 2020, 15:13

Guten Abend,

ich habe den Code auch noch erweitert.
Es geht darum, das man in der praktischen Prüfung an den Stellen, an denen man ganz andere Sachen im Kopf hat, plötzlich nach dem Steuerkurs des Flugzeugs gefragt wird.
An sich ist das einfach, man muss zu einer gegebenen Richtung entweder plus/minus 90 oder plus/minus 180 rechnen. Das Vorzeichen ist noch abhängig davon auf welcher Flugbahn man sich abhängig von dem gegebenen Kurs befindet. Da gibt es den Queranflug (+/- 90) und den Gegenanflug (+/- 180) das sind Standardanflüge. In manchen Fällen kommt man aber von der anderen Seite, dann ist es zum Beispiel der rechte Queranflug und man muss mit den Vorzeichen wieder aufpassen.

Am Montag beim üben, kam ich genau in die Situation, das ich gar nicht damit gerechnet hatte und schon konzentriert auf die erwartete Anweisung war und ich plötzlich nach dem Steuerkurs gefragt wurde. Dabei war ich meiner Meinung nach viel zu langsam und zu dem habe ich auch noch falsch geantwortet. Um da etwas Routine reinzubringen, habe ich noch einen "Navigator" in den Trainer eingebaut. Weil dann zufällig was kommt und ich mir nicht selbst unbewusst die Sachen stelle, die ich weis bzw. da bin ich ja schon darauf vorbereitet.

Naja falls ihr mal drüber schauen wollt, bin ich wie immer über Kritik und Verbesserungen erfreut. Vielleicht ist noch wichtig zu wissen, wenn meine Antwort nicht stimmt, bekomme ich zu hören "[...] bestätigen Sie [...]". Also da ist im Code mit einem einfachen "Falsch" gleichzusetzen.
Den Anlass, das ich euch das wieder zeigen wollte habe ich auch genutzt endlich mal aktiv github.com zu nutzen. Das bietet sich meiner Meinung nach bei einem Projekt mit mehreren Dateien an. Wenn jemand Lust hat kann er das so viel einfach testen.

Wenn es für euch aber geschickter ist, das ich jede Datei hier im Code-Block darstelle, dann mache ich das natürlich.

https://github.com/Dennis-89/BZF-Trainer

Grüße und einen schönen Abend
Dennis
"When I got the music, I got a place to go" [Rancid, 1993]
Antworten