Flask without ORM - Best practices

Viewed 207

I am building a CRUD app using Flask and mySQL without ORM (mostly because I want to be better at SQL and SQLAlchemy is very high level). However, I am concerned about the design and separation of concerns.

This is the overall overview of my application, it's a multi-choice question bank for students (it's far to be done)

blueprints/ ----> admin/
                  user/
                  questions/  
static/
templates/
app.py
database.py

If I am taking the admin/ folder I currently have 2 files (the structure is very similar for every blueprints)

admin/views.py
admin/templates/new-question.html

views.py

from flask import Blueprint, render_template, request
import pymysql
from prepsmarter.extensions import conn #my database pymysql conn variable 

admin = Blueprint('admin', __name__, template_folder='templates')



@admin.route('/users', methods=['GET'])
def get_users():
    sql = "SELECT category_id, category_text FROM category"
    cursor = conn.cursor()
    cursor.execute(sql)    
    categories = cursor.fetchall()
    return render_template('admin/new-question.html', categories=categories)





def insert_answers(question_id, answer_letter, answer_value, correct_answer):
    is_correct = 0
    if answer_letter == correct_answer:
        is_correct = 1
    sql_answer = "INSERT INTO answers (question_id, answer_letter, answer_value, is_correct) VALUES(%s, %s, %s, %s)"
    cursor = conn.cursor()
    cursor.execute(sql_answer, (question_id, answer_letter, answer_value, is_correct))
    cursor.fetchall()
    conn.commit()
    
    

@admin.route('/add_contributor',methods = ['POST'])
def add_contributor():
    name = request.form.get('contrib_name')
    category = request.form.get('category_id')
    question = request.form.get('question')
    answer_a = request.form.get('answer_a')
    answer_b = request.form.get('answer_b')
    answer_c = request.form.get('answer_c')
    correct_answer = request.form.get('correct_answer')
    
    sql_1 = "INSERT INTO contributors (name) VALUES (%s)"
    sql_3 = "INSERT INTO questions (contributor_id, question_text, category_id) VALUES (%s, %s, %s)"
        
        
    cursor = conn.cursor()
    cursor.execute(sql_1, name)
    cursor.fetchall()
    contrib_id = cursor.lastrowid
    conn.commit()
    

    cursor_3 = conn.cursor()
    cursor_3.execute(sql_3, (contrib_id,question, category))    
    cursor_3.fetchall()
    question_id = cursor_3.lastrowid
    conn.commit()  
    
    insert_answers(question_id, "A", answer_a, correct_answer)
    insert_answers(question_id, "B", answer_b, correct_answer)
    insert_answers(question_id, "C", answer_c, correct_answer)
    

    return "ok"

new-question.html

<body>
    <section>
        <form method="POST" action="{{url_for('admin.add_contributor')}}">
            <div>
                <label for="contrib_name">Name</label>
                <input type="text" name="contrib_name">
            </div>

            <div>
                <label for="category">category</label>
                <select name="category_id" id="">
                    {% for category in categories %}
                        <option value="{{ category[0] }}">{{category[1]}}</option>
                    {% endfor %}
                </select>
            </div>

            <div>
                <label for="question">Question</label>
            <textarea name="question" cols="30" rows="10"></textarea>
            </div>

            <div>
                <label for="answer_a">Answer A</label>
                <input type="text" name="answer_a">  
            </div>

            <div>
                <label for="answer_b">Answer B</label>
                <input type="text" name="answer_b">  
            </div>

            <div>
                <label for="answer_c">Answer C</label>
                <input type="text" name="answer_c">  
            </div>

            <div>
                <select name="correct_answer" id="">
                    <option value="A">A</option>
                    <option value="B">B</option>
                    <option value="C">C</option>
                </select>
            </div>

 
            <button type="submit">Submit</button>
        </form>
    </section>
</body>

Should I make a Python class to represent a question as an Object? I am not sure if it's a good practice to directly write SQL code under every methods on my routes.py, every Flask code I saw online is using ORM so not quite confident.

If I am making a class I will clearly have those attributes (which as split into 3 different tables on my db: category, questions, answers).

  • Category
  • Question-text
  • Answers
  • Correct Answer
  • Contributor
0 Answers
Related