Flask Blueprints Sinhala Guide | Python Web App Structure & Scalability

Flask Blueprints: ලොකු Flask Apps හදන්න හොඳම ක්රමය | Sinhala Guide
ආයුබෝවන් යාළුවනේ! අද අපි කතා කරන්න යන්නේ Python web development වල තියෙන සුපිරිම concept එකක් ගැන – ඒ තමයි Flask Blueprints. ඔයාලා Flask එක්ක පොඩි project එකක් කරලා ඇති, එතකොට සමහරවිට ඔක්කොම code ටික එක app.py
file එකක් ඇතුළේ ලියලා ඇති. ඒක පොඩි project වලට නම් අවුලක් නෑ. ඒත් project එක ලොකු වෙනකොට, features වැඩි වෙනකොට, app.py
file එකත් බැලුම් බෝලයක් වගේ ලොකු වෙන්න පටන් ගන්නවා.
එතකොට වෙන්නේ මොකක්ද? Code එක manage කරන්න, අලුත් feature එකක් add කරන්න, නැත්නම් bug එකක් fix කරන්න හරිම අමාරු වෙනවා. Code එක අවුල් වෙලා, එකම file එකේ දහස් ගණන් lines තියෙනකොට බලන්නත් එපා වෙනවා නේද? 😓
මෙන්න මේකට තමයි Flask Blueprints කියන solution එක තියෙන්නේ. Blueprints කියන්නේ ඔබේ Flask application එක විවිධ කොටස් වලට, නැත්නම් "mini-applications" වලට කඩලා, organized විදිහට maintain කරන්න උදව් කරන බලගතු tool එකක්. මේ article එකෙන් අපි බලමු:
- Blueprints කියන්නේ මොනවාද? (The theory behind Blueprints)
- සරල Flask App එකක් Blueprints වලින් Organize කරමු (Practical refactoring with code examples)
- Blueprints එක්ක වැඩ කරනකොට එන පොදු ගැටලු සහ විසඳුම් (Troubleshooting common issues like Circular Imports)
- Best Practices: විශාල Flask Apps සඳහා Modularity (How to build scalable Flask applications)
ඔයාලා සූදානම් නම්, අපි පටන් ගමු!
1. Blueprints කියන්නේ මොනවාද?
සරලව කිව්වොත්, Flask Blueprint
එකක් කියන්නේ Flask application එකේ කොටසක් වෙනම, self-contained module එකක් විදිහට define කරන්න පුළුවන් ක්රමයක්. හරියට ඔබේ ගෙදර විවිධ කාමර වගේ. සාලෙ, නිදන කාමරය, කුස්සිය වගේ. හැම කාමරයකටම තමන්ගේම වැඩ තියෙනවා, ඒත් අන්තිමට ඒ ඔක්කොම එකතු වෙලා තමයි සම්පූර්ණ ගෙදර හැදෙන්නේ.
ඒ වගේම Blueprint
එකකට තමන්ටම කියලා views
(routes), templates
, static files
(CSS, JavaScript), සහ error handlers
තියෙන්න පුළුවන්. Blueprint
එකක් direct run කරන්න බෑ. ඒවා register කරන්න ඕනේ ප්රධාන Flask application
එකට. මේකෙන් වෙන්නේ Flask application
එක කොටස් වලට බෙදිලා යන එක. උදාහරණයක් විදිහට:
- User Management: (Login, Register, Profile) වලට වෙනම
auth_bp
(Blueprint) එකක්. - Product Catalog: (View Products, Add Product, Edit Product) වලට තව
product_bp
එකක්. - Admin Panel: (Manage Users, View Reports) වලට තව
admin_bp
එකක්.
මේ වගේ organize කිරීමෙන් code එක කියවන්න, තේරුම් ගන්න, develop කරන්න හරිම පහසු වෙනවා. ඒ වගේම එකම project එකේ කීප දෙනෙකුට එකට වැඩ කරන්නත් පුළුවන්, එකිනෙකාගේ code එක collide වෙන්නේ නැතුව.
2. සරල Flask App එකක් Blueprints වලින් Organize කරමු
දැන් අපි බලමු practical විදිහට Blueprints කොහොමද use කරන්නේ කියලා. මුලින්ම අපි සාමාන්ය Flask app එකක් (Blueprints නැතුව) කොහොමද තියෙන්නේ කියලා බලමු, ඊට පස්සේ ඒක Blueprints වලින් refactor කරමු.
2.1. සාමාන්ය Flask App එකක් (Blueprints නැතුව)
පහළ තියෙන්නේ routes කීපයක් තියෙන සරල Flask app එකක්. හැමදේම තියෙන්නේ එක app.py
file එකක් ඇතුළේ.
# app.py (Without Blueprints)
from flask import Flask, render_template
app = Flask(__name__)
@app.route('/')
def index():
return "Welcome to the Home Page!"
@app.route('/about')
def about():
return "This is the About Page."
@app.route('/contact')
def contact():
return "Contact us at [email protected]"
# User related routes
@app.route('/login')
def login():
return "Login Page"
@app.route('/register')
def register():
return "Register Page"
if __name__ == '__main__':
app.run(debug=True)
මේක පොඩි app එකක් වුනාට, හිතන්න මේකට තව routes 50ක්, 100ක් විතර එකතු වුනොත්? Database interactions, form handling, authentication logic ඔක්කොම එකම file එකක තිබ්බොත් වැඩේ කොච්චර අවුල් වෙයිද?
2.2. Blueprints හඳුන්වාදීම
දැන් අපි අපේ application එක Blueprints වලින් organized කරගමු. අපි auth
(authentication related routes වලට) සහ views
(general public routes වලට) කියලා Blueprints දෙකක් හදාගමු. අපේ project structure එක මේ වගේ වෙන්න ඕනේ:
project_root/
├── app.py
├── auth/ # Authentication Blueprint folder
│ ├── __init__.py
│ └── auth.py
├── views/ # General views Blueprint folder
│ ├── __init__.py
│ └── views.py
└── templates/ # Main templates folder
├── base.html
├── auth/ # Auth Blueprint's templates
│ ├── login.html
│ └── register.html
└── views/ # Views Blueprint's templates
├── home.html
└── dashboard.html
දැන් අපි එක් එක් file එකට code එක ලියමු:
auth/auth.py
file එක
මේ Blueprint
එක user authentication
(Login, Register, Logout) routes ටික handle කරනවා.
# auth/auth.py
from flask import Blueprint, render_template, request, flash, redirect, url_for
# Blueprint එකක් හදාගන්නවා
# 'auth' කියන්නේ Blueprint එකේ name එක
# __name__ කියන්නේ Blueprint එකේ root path එක.
# url_prefix='/auth' කියන්නේ මේ Blueprint එකේ හැම route එකකටම '/auth' prefix එකක් add වෙනවා.
auth_bp = Blueprint('auth', __name__, url_prefix='/auth', template_folder='templates')
@auth_bp.route('/login', methods=['GET', 'POST'])
def login():
if request.method == 'POST':
username = request.form['username']
password = request.form['password']
if username == 'admin' and password == 'password': # Simple, insecure check for demonstration
flash('Login successful!', 'success')
return redirect(url_for('views.home')) # Redirect to a view in another Blueprint
else:
flash('Invalid credentials!', 'danger')
return render_template('auth/login.html') # Note: Flask will search in auth/templates/login.html first
@auth_bp.route('/register')
def register():
return render_template('auth/register.html')
@auth_bp.route('/logout')
def logout():
flash('Logged out successfully!', 'info')
return redirect(url_for('views.home'))
views/views.py
file එක
මේ Blueprint
එක general public views (Home, Dashboard) handle කරනවා.
# views/views.py
from flask import Blueprint, render_template, flash
# Blueprint එකක් හදාගන්නවා
# 'views' කියන්නේ Blueprint එකේ name එක
# මේකට url_prefix එකක් දුන්නේ නැති නිසා මේක root path එකේ mount වෙනවා.
views_bp = Blueprint('views', __name__, template_folder='templates')
@views_bp.route('/')
def home():
flash('Welcome to the Blueprint Home!', 'info')
return render_template('views/home.html')
@views_bp.route('/dashboard')
def dashboard():
return render_template('views/dashboard.html')
app.py
file එක (අවසානයි)
දැන් අපේ ප්රධාන app.py
file එකේ කරන්නේ, අපි හදපු Blueprints දෙක import කරලා, ඒවා ප්රධාන Flask application
එකට register කරන එක විතරයි. බලන්න code එක කොච්චර clean වෙලාද කියලා!
# app.py (With Blueprints)
from flask import Flask
# Blueprints දෙක import කරගන්නවා.
# මේවා auth/auth.py සහ views/views.py files වලින් එන Blueprints.
from auth.auth import auth_bp
from views.views import views_bp
app = Flask(__name__)
app.config['SECRET_KEY'] = 'your_super_secret_key_here' # For flash messages
# Blueprints register කරනවා.
# මේකෙන් තමයි Flask application එකට Blueprint routes හඳුන්වා දෙන්නේ.
app.register_blueprint(auth_bp)
app.register_blueprint(views_bp)
if __name__ == '__main__':
app.run(debug=True)
Templates files (උදාහරණ)
අපේ Templates folder එකත් මේ විදිහට හදාගමු. Flask render_template()
function එක Blueprint එකක් ඇතුළේ use කරනකොට, මුලින්ම බලන්නේ ඒ Blueprint එකේ template_folder
එකේ (අපි template_folder='templates'
කියලා දුන්න නිසා ඒ Blueprint folder එක ඇතුළේ තියෙන templates
folder එකේ) අදාළ template file එක තියෙනවද කියලා. එහෙම නැතිනම් ප්රධාන app
එකේ templates
folder එකේ බලනවා. මේ නිසා auth
Blueprint එකේ templates auth
folder එක ඇතුළෙත්, views
Blueprint එකේ templates views
folder එක ඇතුළෙත් තියෙන එක හොඳ පුරුද්දක්.
templates/base.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{% block title %}My Flask App{% endblock %}</title>
<style>
body { font-family: sans-serif; margin: 20px; }
nav a { margin-right: 15px; text-decoration: none; color: #007bff; }
nav a:hover { text-decoration: underline; }
.flash { padding: 10px; margin-bottom: 10px; border-radius: 5px; }
.flash.success { background-color: #d4edda; color: #155724; border-color: #c3e6cb; }
.flash.info { background-color: #d1ecf1; color: #0c5460; border-color: #bee5eb; }
.flash.danger { background-color: #f8d7da; color: #721c24; border-color: #f5c6cb; }
</style>
</head>
<body>
<nav>
<a href="{{ url_for('views.home') }}">Home</a> |
<a href="{{ url_for('auth.login') }}">Login</a> |
<a href="{{ url_for('auth.register') }}">Register</a> |
<a href="{{ url_for('auth.logout') }}">Logout</a>
</nav>
{% with messages = get_flashed_messages(with_categories=true) %}
{% if messages %}
<ul class="flashes">
{% for category, message in messages %}
<li class="flash {{ category }}">{{ message }}</li>
{% endfor %}
</ul>
{% endif %}
{% endwith %}
<hr>
<div class="content">
{% block content %}{% endblock %}
</div>
</body>
</html>
templates/auth/login.html
{% extends 'base.html' %}
{% block title %}Login{% endblock %}
{% block content %}
<h2>Login Page</h2>
<form method="POST">
<label for="username">Username:</label><br>
<input type="text" id="username" name="username"><br>
<label for="password">Password:</label><br>
<input type="password" id="password" name="password"><br><br>
<input type="submit" value="Login">
</form>
{% endblock %}
templates/views/home.html
{% extends 'base.html' %}
{% block title %}Home{% endblock %}
{% block content %}
<h1>Welcome!</h1>
<p>This is the home page of our Blueprint-powered Flask app.</p>
{% endblock %}
දැන් ඔයාට මේ application
එක run කරලා බලන්න පුළුවන්. `python app.py` කියලා run කරලා `http://127.0.0.1:5000/` ට ගියාම `Home` page එක පෙනෙයි. `http://127.0.0.1:5000/auth/login` ට ගියාම `Login` page එක පෙනෙයි. `url_for('views.home')` වගේ `url_for` එක use කරනකොට `Blueprint` එකේ name එක මුලින් දීලා, ඊට පස්සේ `view function` එකේ name එක දෙන්න ඕනේ.
3. Blueprints එක්ක වැඩ කරනකොට එන පොදු ගැටලු සහ විසඳුම්
Blueprints කියන්නේ හරිම powerful, නමුත් ඒවා use කරනකොට පොඩි පොඩි issues එන්න පුළුවන්. ඒ අතරින් බහුලවම එන ගැටලුවක් තමයි Circular Imports.
3.1. Circular Imports (චක්රීය ආනයන)
Circular Import
එකක් කියන්නේ, Module A
එක Module B
එක import කරනවා, ඒ වගේම Module B
එකත් Module A
එක import කරනවා. මේක "import loop" එකක්. Python වලදී මේ වගේ වෙලාවට ImportError
එකක් හෝ undefined names වගේ errors එන්න පුළුවන්.
Flask වලදී මේක වෙන්නේ කොහොමද?
- ඔබේ
Blueprint
module එකක් (උදා:auth.py
) ප්රධානapp
instance එකapp.py
එකෙන් direct import කරන්න හැදුවොත්. Blueprint
එකක් තවBlueprint
එකක් import කරන්න හැදුවොත් (මේක සාමාන්යයෙන් කරන්න හොඳ නෑ).
app.py
එක auth.py
import කරනවා. auth.py
එකත් app.py
import කරනවා නම් මේක circular import එකක්. Flask වල app
instance එකට direct access නැතුවට, config variables වගේ දේවල් access කරන්න ඕන වෙන වෙලාවට මේ වගේ අවුල් ඇතිවෙන්න පුළුවන්.
විසඳුම: current_app
proxy එක භාවිතය
Flask වලට current_app
කියලා special proxy එකක් තියෙනවා. මේකෙන් පුළුවන් දැනට active වෙලා තියෙන Flask application
instance එකට access කරන්න. මේක request context
එක ඇතුළේ වැඩ කරන නිසා Circular Import
ගැටලු මඟහරවා ගන්න පුළුවන්.
# auth/auth.py (Avoiding Circular Imports with current_app)
from flask import Blueprint, render_template, request, flash, redirect, url_for, current_app
auth_bp = Blueprint('auth', __name__, url_prefix='/auth', template_folder='templates')
@auth_bp.route('/login', methods=['GET', 'POST'])
def login():
if request.method == 'POST':
# Accessing app config safely without importing 'app' directly
secret_key = current_app.config['SECRET_KEY']
print(f"Using secret key: {secret_key}")
# ... rest of your login logic
flash('Login successful!', 'success')
return redirect(url_for('views.home'))
return render_template('auth/login.html')
මේ විදිහට current_app
use කරනකොට, Blueprint
modules වලට app
instance එක direct import කරන්න ඕන වෙන්නේ නෑ. මේක Circular Imports
වළක්වා ගන්න හොඳම ක්රමයක්.
3.2. Static Files සහ Templates කළමනාකරණය
Blueprints වලට තමන්ගේම static_folder
සහ template_folder
specify කරන්න පුළුවන්. මේකෙන් වෙන්නේ ඒ Blueprint එකට අදාළ resources ඒ Blueprint එක ඇතුළේම තියාගන්න පුළුවන් වෙන එක.
# Blueprint එකක් හදනකොට template_folder සහ static_folder specify කරන්න පුළුවන්
auth_bp = Blueprint(
'auth',
__name__,
url_prefix='/auth',
template_folder='templates', # Looks for templates inside auth/templates/
static_folder='static' # Looks for static files inside auth/static/
)
Templates: render_template('auth/login.html')
වගේ එකක් use කරනකොට, Flask මුලින්ම බලන්නේ auth
Blueprint එකේ template_folder
එක ඇතුළේ login.html
තියෙනවද කියලා (අපි template_folder='templates'
දුන්න නිසා auth/templates/login.html
). ඊට පස්සේ තමයි ප්රධාන app
එකේ templates
folder එකේ බලන්නේ. මේ නිසා Template namespaces කරලා තියාගන්න එක හොඳ පුරුද්දක්.
Static Files: url_for()
function එක use කරලා Blueprint
එකක static files වලට link කරන්න පුළුවන්. උදාහරණයක් විදිහට, auth
Blueprint එකේ static/css/style.css
file එකට link කරන්න ඕනේ නම්:
{{ url_for('auth.static', filename='css/style.css') }}
මතක තියාගන්න, 'auth'
කියන්නේ Blueprint
එකේ name එක, 'static'
කියන්නේ Flask එකේ static files serve කරන්න තියෙන විශේෂ endpoint එක.
4. Best Practices: Scalable Flask Apps සඳහා Modularity
Blueprints වලින් උපරිම ප්රයෝජන ගන්න නම්, මේ best practices
ටික follow කරන එක වැදගත්.
Database Management
ඔබේ database models
, forms
, utilities
වගේ දේවල් වෙනම modules වල තියාගන්න. මේවා Blueprint
එකක් ඇතුළේ direct define කරනවට වඩා, `models.py`, `forms.py` වගේ files වල තියාගන්න එක හොඳයි. Blueprints වලට අවශ්ය නම් මේවා import කරගන්න පුළුවන්. SQLAlchemy
වගේ ORM එකක් use කරනකොට, database instance
එක Blueprint
එකට direct pass කරනවා වෙනුවට, current_app
use කරලා app context
එක ඇතුළේ access කරන එක circular import
ගැටලු වළක්වා ගන්න උදව් කරනවා.
Application Factory Pattern
ඉතා විශාල application
වලට, විශේෂයෙන් testing
වලට, application factory pattern
එකක් use කරන එක හොඳ පුරුද්දක්. මේකේදී create_app()
වගේ function
එකක් ඇතුළේ Flask app
instance එක හදලා, configuration
කරලා, Blueprints
register කරලා return කරනවා. මේකෙන් app එකේ dependencies manage කරන්න සහ test කරන්න හරිම පහසුයි.
# app.py (using an Application Factory)
from flask import Flask
def create_app():
app = Flask(__name__)
app.config['SECRET_KEY'] = 'another_super_secret_key'
from .auth.auth import auth_bp
from .views.views import views_bp
app.register_blueprint(auth_bp)
app.register_blueprint(views_bp)
return app
if __name__ == '__main__':
app = create_app()
app.run(debug=True)
Naming Conventions
Blueprint
names (උදා: auth
, views
) විස්තරාත්මක (descriptive) සහ unique වෙන්න ඕනේ. url_for('blueprint_name.view_function')
වගේ ඒවා use කරනකොට මේ Blueprint
name එක හරියටම දෙන්න ඕනේ.
Separation of Concerns
හැම Blueprint
එකක්ම එක specific feature set එකක් handle කරන්න ඕනේ. auth
Blueprint
එකට user authentication
විතරක්, products
Blueprint
එකට product management
විතරක්. මේකෙන් code එක maintainability වැඩි වෙනවා, ඒ වගේම අනාගතයේදී වෙන මොඩියුල් එකකට move කරන්න වුනත් පහසුයි.
පැහැදිලි Module Organization
ඔබේ project structure එක හැමෝටම තේරෙන විදිහට clear වෙන්න ඕනේ. අපි උඩින් පෙන්නපු විදිහට auth/
, views/
වගේ folders හදලා, ඒ ඒ Blueprint
එකට අදාළ files (views, templates, static) ඒ folder එක ඇතුළේම තියාගන්න. මේකෙන් Codebase එක clean වෙනවා, අලුත් developer කෙනෙකුට වුනත් project එක ඉක්මනින් තේරුම් ගන්න පුළුවන්.
නිගමනය
හරි, දැන් ඔයාලට Flask Blueprints කියන්නේ මොනවාද, ඒවා කොහොමද use කරන්නේ, සහ ඒවායින් ඔබේ Flask application එක කොච්චර modular සහ scalable කරගන්න පුළුවන්ද කියලා හොඳ අවබෝධයක් ලැබෙන්න ඇති කියලා හිතනවා. Blueprints කියන්නේ Flask හි තියෙන වටිනාම features වලින් එකක්. මේක හරියට use කරන එකෙන් ඔබේ code එකේ quality එක, maintainability එක, සහ team collaboration වල පහසුව විශාල ලෙස වැඩි කරගන්න පුළුවන්.
මුලදී Circular Imports
වගේ පොඩි පොඩි දේවල් ගැන සැලකිලිමත් වෙන්න වුනත්, ඒවාට සරල විසඳුම් තියෙනවා (current_app
මතක තියාගන්න!). අන්තිමට ලැබෙන clean, organized codebase එකට ඒ පොඩි මහන්සිය වටිනවා.
ඉතින්, ඔයාලගේ ඊළඟ Flask project එකට Blueprints
පාවිච්චි කරන්න අමතක කරන්න එපා! 🚀 මේකෙන් ලැබෙන වෙනස ඔයාලටම බලාගන්න පුළුවන්. මේ ගැන ඔයාලගේ අත්දැකීම්, ප්රශ්න, නැත්නම් අලුත් අදහස් පහළ comment
section එකේ දාන්න. අපි කතා කරමු!
Happy Coding! 😊