Home > Courses > Flask: Python Web Development > Structure flask app using Blueprint

Structure flask app using Blueprint

Subject: Flask: Python Web Development
As our application get bigger as we can see in our last example, it can become complex and difficult to manage as all our code cannot fit in well in one app.py files (it would be very messy if we try to....).

Flask uses a concept of blueprints for making application components to help us to organise large applications into smaller, manageable components, leading to enhanced maintainability of the application.

Blueprints can greatly simplify how large applications work and provide a central means for Flask extensions to register operations on applications.

A Blueprint object works similarly to a Flask application object, but it is not actually an application. Rather it is a blueprint of how to construct or extend an application.

modularising our School Grading System web app project
As you may notice the app.py is having more code already besides we still plan to include the edit and delete function to students record, instructor, subjects and student score functions too will be implemented, followed by admin register with login. These will be too much and confusing for us to have all that code in our app.py file.

So will modularise or structure our code into smaller units inside several python files using Blueprint, register them in the app.py so as access them.

Database connection
When we had all the code in the app.py it was fine having the database connect string in the app.py since all the code or function that need database access resides in that app.py file, however now that we are trying to split the code into several files, it will be a bad practice copying the database connection string:


conn = sqlite3.connect('tealearn_grades.db', check_same_thread=False) 


and pasting it in all the python files that will be needing database access, because the database name may change or we may choose to use MySQL database instead of SQLite in production therefore it will become a nightmare maintaining our code if we have 100 python files accessing the database.

So let us create a files name database.py in the same location as your app.py file to hold this essential information so that all other python files that need database connection can import it.

student_score/database.py

import sqlite3 
import os
dir_path = os.path.dirname(os.path.realpath(__file__))

def connect_db():
		#create and connect to the database
		conn = sqlite3.connect(dir_path+'/tealearn_grades.db', check_same_thread=False) 
		return conn



Student Blueprint
Now I created a file name student_blueprint.py with the code:

student_score/student_blueprint.py

from flask import Blueprint, render_template, request

from database import connect_db
conn = connect_db()

student_bp=Blueprint("student_blueprint", __name__, static_folder="static", template_folder="templates")

#load form
@student_bp.route('/student') 
def student():
	return render_template('student.html')

#display record
@student_bp.route('/seestudents') 
def seestudents():
	 cursor = conn.cursor() 
	 cursor.execute('SELECT * FROM student')
	 data = cursor.fetchall()
	 return render_template('seestudents.html', students=data)
	 
	 
#process the student add
@student_bp.route('/addstudent', methods=['GET', 'POST']) 
def addstudent(): 
  if request.method == 'POST': 
    surname = request.form['surname'] 
    othernames = request.form['othernames'] 
    address = request.form['address'] 
    
    conn.execute('INSERT INTO student (surname_name,other_name,address_address) VALUES (?,?,?)',(surname, othernames, address)) 
    conn.commit() 
    output="Student record saved"
  return render_template('student.html', msg=output) 


Notice that we:
import Blueprint, render template, request and the database connection connect_db function.

Created the blueprint name student_bp set it's parameters

Use the blueprint name student_bp to create the routes. Notice that the code block in each route function was extracted from our app.py but instead of @app.route('/student') we now have @student_bp.route('/student')


Tables Creation Blueprint
I also created a file name "table_create_blueprint.py" to handle the tables creation code:

student_score/table_create_blueprint.py

from flask import Blueprint, render_template, request

from database import connect_db
conn = connect_db()

tables_bp=Blueprint("table_create_blueprint", __name__,  template_folder="templates")


#setup the tables in the database
@tables_bp.route('/dbsetup') 
def dbsetup(): 

	sql_create_student_table='CREATE TABLE  IF NOT EXISTS student (student_id INTEGER PRIMARY KEY, surname_name TEXT, other_name TEXT, address_address TEXT)'

	sql_create_instructor_table='CREATE TABLE IF NOT EXISTS instructor (instructor_id INTEGER PRIMARY KEY, surname_name TEXT, other_name TEXT, address_address TEXT, qualification TEXT)'

	sql_create_subject_table='CREATE TABLE IF NOT EXISTS subject (subject_id INTEGER PRIMARY KEY, instructor_id INTEGER, subject_title TEXT, more_detail TEXT, max_score INTEGER)'

	sql_create_score_table='CREATE TABLE IF NOT EXISTS student_score (score_id INTEGER PRIMARY KEY, score_value INTEGER, student_id  INTEGER, subject_id INTEGER)'

	try:
		#use the connection to execute the queries to create the tables
		conn.execute(sql_create_student_table)
		conn.commit()
		
		conn.execute(sql_create_instructor_table)
		conn.commit()
		
		conn.execute(sql_create_subject_table)
		conn.commit()
		
		conn.execute(sql_create_score_table)
		conn.commit()
		
		output="db setup successful"
	except sqlite3.Error as er:
		output=er.sqlite_errorname
		
	return render_template('dbsetup.html', msg=output) 


App.py file
Here is now what our app.py looks like now:

student_score/app.py

from flask import Flask, render_template, request 

from database import connect_db
conn = connect_db()

from student_blueprint import student_bp
from table_create_blueprint import tables_bp

app = Flask(__name__) 
#register or access the blueprints
app.register_blueprint(student_bp)
app.register_blueprint(tables_bp)


#load the home or index page
@app.route('/home') 
@app.route('/') 
def index(): 
  return render_template('index.html') 

if __name__ == '__main__': 
       app.run(debug=True)    


Notice that the app.py file is looking cleaner with only the index view. We have imported both blueprints and register them, that is all to it. Well done! if you have come this far.


Files





By: Benjamin Onuorah

Comments

No Comment yet!

Login to comment or ask question on this topic


Previous Topic Next Topic

Supported by