<repo_name>kokot300/quiz_flask<file_sep>/flask_app.py
#!/usr/bin/python

from flask import Flask, render_template, request
from models import Question, Category
import api_handler
from random import shuffle

app = Flask(__name__)

questions_lst2 = []
api_question_lst = []


@app.route('/', methods=['GET', 'POST'])
def root():
    if request.method == 'GET':
        return render_template('index.html')
    else:
        return render_template('index.html')


@app.route('/quiz', methods=['GET', 'POST'])
def quiz():
    global questions_lst2
    categories = Category.get_all_cat()
    if request.method == 'GET':
        return render_template('quiz_select_cat.html', categories=categories)
    else:
        where = request.form.get('where')
        if where == '0':
            questions_lst2 = []
            category = request.form.get('category')
            if category == 'All':
                category = None
            else:
                category = Category.get_cat_by_name(category)
                category = category[0]
                print(category)
            questions_lst = Question.get_5_random(category)
            print(questions_lst)
            for idd in questions_lst:
                ask = Question.get_from_class_id(idd)
                ask = str(ask)
                ask_lst = ask.split('/')
                questions_lst2.append(ask_lst)
            return render_template('quiz_challenge.html', questions_lst2=questions_lst2)
        elif where == '1':
            answer_lst = []
            try:
                for answer in questions_lst2:
                    ans = answer[6]
                    answer_lst.append(ans)
                question_id_lst = []
                for question_id in questions_lst2:
                    ques = question_id[0]
                    question_id_lst.append(ques)

                user_answers = []
                first_question = request.form.get(question_id_lst[0])
                second_question = request.form.get(question_id_lst[1])
                third_question = request.form.get(question_id_lst[2])
                fourth_question = request.form.get(question_id_lst[3])
                fifth_question = request.form.get(question_id_lst[4])
                user_answers.append(first_question)
                user_answers.append(second_question)
                user_answers.append(third_question)
                user_answers.append(fourth_question)
                user_answers.append(fifth_question)
                print(user_answers)

                score = 0
                for i in range(5):
                    if user_answers[i] == answer_lst[i]:
                        score += 1

                return render_template('quiz_results.html', questions_lst2=questions_lst2, user_answers=user_answers,
                                       score=score)
            except IndexError:
                return render_template('quiz_select_cat.html', categories=categories)
        else:
            return render_template('quiz_select_cat.html', categories=categories)


@app.route('/quiz_api', methods=['GET', 'POST'])
def quiz_api():
    global api_question_lst
    categories = api_handler.get_cats()
    if request.method == 'GET':
        return render_template('quiz_api_select_cat.html', categories=categories)
    else:
        where = request.form.get('where')
        print(where)
        if where == '0':
            api_question_lst = []
            category = request.form.get('category')
            if category == 'All':
                category = None
            print(category)
            questions = api_handler.get_questions(category)
            print(questions)
            question_lst = []
            for question in questions:
                answers = question['incorrect_answers']
                answers.append(question['correct_answer'])
                shuffle(answers)
                question_lst.append(question['question'])
                question_lst.append(answers)
                question_lst.append(question['correct_answer'])
                api_question_lst.append(question_lst)
                question_lst = []
            return render_template('quiz_api_challenge.html', questions=api_question_lst)
        elif where == '1':
            answer_lst = []
            try:
                for answer in api_question_lst:
                    ans = answer[2]
                    answer_lst.append(ans)
                question_id_lst = []
                for question_id in api_question_lst:
                    ques = question_id[0]
                    question_id_lst.append(ques)

                user_answers = []
                first_question = request.form.get(question_id_lst[0])
                second_question = request.form.get(question_id_lst[1])
                third_question = request.form.get(question_id_lst[2])
                fourth_question = request.form.get(question_id_lst[3])
                fifth_question = request.form.get(question_id_lst[4])
                user_answers.append(first_question)
                user_answers.append(second_question)
                user_answers.append(third_question)
                user_answers.append(fourth_question)
                user_answers.append(fifth_question)

                score = 0
                for i in range(5):
                    if user_answers[i] == answer_lst[i]:
                        score += 1
            except:
                pass
            return render_template('quiz_api_results.html', api_question_lst=api_question_lst, user_answers=user_answers,
                                   score=score)
        else:
            return render_template('quiz_api_select_cat.html', categories=categories)


@app.route('/add_question', methods=['GET', 'POST'])
def add_question():
    if request.method == 'GET':
        categories = Category.get_all_cat()
        return render_template('add_question.html', categories=categories)
    else:
        categories = Category.get_all_cat()
        question = request.form.get('question')
        a = request.form.get('a').lower()
        b = request.form.get('b').lower()
        c = request.form.get('c').lower()
        d = request.form.get('d').lower()
        correct = request.form.get('correct').lower()

        category = request.form.get('category').lower()
        category = Category.get_cat_by_name(category)
        category = category[0]

        print(question, a, b, c, d, correct, category)

        msg = Question.creator(question, a, b, c, d, correct, category)
        print(msg)

        return render_template('add_question.html', categories=categories, msg=msg.add_to_db())


@app.route('/add_category', methods=['GET', 'POST'])
def add_category():
    if request.method == 'GET':
        return render_template('add_category.html')
    else:
        candidate = request.form.get('category').lower()
        new_cat = Category.creator(candidate)

        return render_template('add_category.html', msg=new_cat.add_to_db())


if __name__ == '__main__':
    app.run(debug=True)
<file_sep>/models.py
#!/usr/bin/python

from psycopg2 import connect, OperationalError, errors
from random import shuffle

USER = 'kokot300'
PASSWORD = ''
HOST = 'localhost'
DATABASE = 'quiz_db'


class Question:
    @classmethod
    def creator(cls, question, aaa, bbb, ccc, ddd, correct, category_id):
        if not isinstance(question, str):
            return 'classmethod says: question must be a string'
        if not isinstance(aaa, str) or len(aaa) > 60:
            return 'classmethod says: aaa must be a string of 60 chars max'
        if not isinstance(bbb, str) or len(bbb) > 60:
            return 'classmethod says: bbb must be a string of 60 chars max'
        if not isinstance(ccc, str) or len(ccc) > 60:
            return 'classmethod says: aaa must be a string of 60 chars max'
        if not isinstance(ddd, str) or len(ddd) > 60:
            return 'classmethod says: ddd must be a string of 60 chars max'
        if not isinstance(correct, str) or len(correct) > 60:
            return 'classmethod says: correct must be a string of 1 char max'
        if category_id:
            pass
        return cls(question, aaa, bbb, ccc, ddd, correct, category_id)

    def __init__(self, question, aaa, bbb, ccc, ddd, correct, category_id, idd=-1):
        self.question = question
        self.aaa = aaa
        self.bbb = bbb
        self.ccc = ccc
        self.ddd = ddd
        self.correct = correct
        self.category_id = category_id  # provisory
        self.id = idd

    def add_to_db(self):
        command = f'''INSERT INTO questions(question, aaa, bbb, ccc, ddd, correct, category_id) VALUES (%s, %s, %s, %s, %s, %s, %s);'''
        tlp = (self.question, self.aaa, self.bbb, self.ccc, self.ddd, self.correct, self.category_id)
        cursor = Question.connect_me()
        try:
            cursor.execute(command, tlp)
        except OperationalError as e:
            print(e)
            return f'{e}'
        except errors.UniqueViolation as e:
            return f'{e}'
        else:
            cursor.close()
            return 'added'

    @staticmethod
    def get_from_class_id(question_id):
        command = '''SELECT question, aaa, bbb, ccc, ddd, correct, category_id, id FROM questions WHERE id = %s;'''
        tlp = (question_id,)
        cursor = Question.connect_me()
        try:
            cursor.execute(command, tlp)
            data = cursor.fetchone()  # tuple
        except OperationalError as e:
            print(e)
            return f'{e}'
        else:
            cursor.close()
            if data is not None:
                new_question = Question(data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7])
                return new_question

    @staticmethod
    def connect_me():
        try:
            cnx = connect(
                user=USER,
                password=<PASSWORD>,
                host=HOST,
                database=DATABASE
            )
            cnx.autocommit = True
            cursor = cnx.cursor()
            return cursor
        except OperationalError as e:
            print(e)
            return f'{e}'

    def __str__(self):
        return f'{self.id}/{self.question}/{self.aaa}/{self.bbb}/{self.ccc}/{self.ddd}/{self.correct}/{self.category_id}'

    @staticmethod
    def get_5_random(category=None):
        cursor = Question.connect_me()
        if category is None:
            command = '''SELECT id FROM questions;'''
            try:
                cursor.execute(command)
                data = cursor.fetchall()  # list of tuples
            except OperationalError as e:
                print(e)
                return f'{e}'

        else:
            command = '''SELECT id FROM questions WHERE category_id = %s;'''
            tlp = (category,)

            try:
                cursor.execute(command, tlp)
                data = cursor.fetchall()  # tuple
            except OperationalError as e:
                print(e)
                return f'{e}'
        cursor.close()
        shuffle(data)
        print('data in models', data)
        return data[0:5]


class Category:
    @classmethod
    def creator(cls, name):
        if len(name) <= 60:
            return cls(name)

    def __init__(self, name):
        self.name = name
        self.id = -1

    @staticmethod
    def connect_me():
        try:
            cnx = connect(
                user=USER,
                password=<PASSWORD>,
                host=HOST,
                database=DATABASE
            )
            cnx.autocommit = True
            cursor = cnx.cursor()
            return cursor
        except OperationalError as e:
            print(e)
            return f'{e}'

    def add_to_db(self):
        command = f'''INSERT INTO categories(name) VALUES (%s);'''
        tlp = (self.name,)
        cursor = Question.connect_me()
        try:
            cursor.execute(command, tlp)
        except OperationalError as e:
            print(e)
            return f'{e}'
        except errors.UniqueViolation as e:
            return f'{e}'
        else:
            cursor.close()
            return 'added'

    @staticmethod
    def validate_category(name):
        command = f"""SELECT * FROM categories WHERE name = %s;"""
        tlp = (name,)
        cursor = Question.connect_me()
        try:
            cursor.execute(command, tlp)
        except OperationalError as e:
            print(e)
            return f'{e}'
        else:
            data = cursor.fetchone()
            cursor.close()
            print(data)
            if data is None:
                return False
            return True

    @staticmethod
    def get_cat_by_name(name):
        command = f"""SELECT id FROM categories WHERE name = %s;"""
        tlp = (name,)
        cursor = Question.connect_me()
        try:
            cursor.execute(command, tlp)
        except OperationalError as e:
            print(e)
            return f'{e}'
        else:
            data = cursor.fetchone()
            cursor.close()
            print(data)
            return data

    @staticmethod
    def get_all_cat():
        command = f"""SELECT name FROM categories;"""
        cursor = Question.connect_me()
        try:
            cursor.execute(command)
        except OperationalError as e:
            print(e)
            return f'{e}'
        else:
            data = cursor.fetchall()
            cursor.close()
            return data

    def __str__(self):
        return f'{self.id}, {self.name}'


if __name__ == '__main__':
    pass
    # q = Question('kto jest najpiękniejszy na świecie?', 'ja', 'ty', 'on', 'ona', 'a', 1)
    # q.add_to_db()
    # q = Question.get_from_class_id(2)
    # print(q)
    # q = Question.creator('kto jest najsilniejszy na świecie?', 'ja', 'ty', 'on', 'ona', 'd', 1)
    # print(q)
    # q.add_to_db()
    # q = Question.get_5_random()
    # print(q[0][0])
    # Category.validate_category('głupie')
<file_sep>/api_handler.py
#!/usr/bin/python

from requests import get


def get_cats():
    api_endpoint = 'https://opentdb.com/api_category.php'
    response = get(api_endpoint)
    data = response.json()
    return data['trivia_categories']


def get_questions(category=None):
    if category is None:
        api_endpoint = 'https://opentdb.com/api.php?amount=5&type=multiple'
    else:
        api_endpoint = f'https://opentdb.com/api.php?amount=5&category={category}&type=multiple'
    response = get(api_endpoint)
    data = response.json()
    return data['results']


if __name__ == '__main__':
    get_questions()
<file_sep>/create_db.py
q = """create table questions(
id serial, question text,
aaa varchar(60),
bbb varchar(60),
ccc varchar(60),
ddd varchar(60),
correct varchar(1),
category_id int,
when_added timestamp NOT NULL,
PRIMARY KEY (id),
FOREIGN KEY (category_id) REFERENCES categories(id));"""

q2="""CREATE TABLE categories(
id serial,
name varchar(60),
PRIMARY KEY (id)
);"""<file_sep>/README.md
# quiz_flask
quiz on flask and postgresql
