Flask ile geliştirilen uygulamaların standart bir proje mimarisi ile geliştirilmediğini fark etmişsinizdir. Her uygulama, geliştiricisinin kendi kurguladığı proje tasarımı ve uygulama mimarisi ile inşa edilir ve kullanıma sunulur. Bunun en önemli sebebi, Flask’in geliştiricileri bu konuda oldukça özgür bırakmasıdır.
Ancak yine de resmi Flask dokümanlarını incelediğimizde bize önerilen bir tasarım deseninin mevcut olduğunu görüyoruz. Daha önce karşılaştığınızı düşündüğüm bu tasarım desenine Application Factory Pattern yada Türkçe olarak Uygulama Fabrikası Deseni diyoruz. Bizlerde bu makalede, Application Factory Pattern kullanarak bir Flask uygulamasının nasıl en iyi şekilde yapılandırabileceğimizi öğreneceğiz.
Application Factory Pattern Nedir?
Flask ile bir uygulama geliştirdiğimizde, geleneksel yöntemde, bütün uygulama tek bir app nesnesi üzerine inşa edilir ve farklı örnekleri oluşturulamaz. Ancak Application Factory Pattern uygulamayı bir fonksiyon içerisinde yapılandırarak uygulamanın bu fonksiyon ile ayağa kaldırılması ilkesine dayanır. Bu sayede uygulamamızın birden fazla örneğini, birden fazla yapılandırma ayarı ile hızlıca oluşturulup kullanılabilir hale getirebiliriz. Yani özetle AFP;
- Döngüsel içe aktarma problemlerini çözer.
- Farklı ortamlar (development, test, production) için daha hızlı ve daha kolay kurulum sağlar.
- Daha organize ve daha okunabilir kod tabanı oluşturur.
- Sürdürülebilir ve ölçeklenebilir proje mimarileri için alt yapı kurar.
Application Factory Pattern ile Uygulama Geliştirmek
Örneğin, aşağıda SQLAlchemy ile desteklenmiş basit bir web uygulamasını görebilirsiniz.
from flask import Flask, render_template
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
db = SQLAlchemy(app)
@app.route("/")
@app.route("/index")
def index():
return render_template("index.html")
Geleneksel yöntemlerle geliştirdiğimiz uygulamamızda, 4. satırda hızlıca app = Flask(__name__)
diyerek uygulamamızı oluşturduk. Gördüğünüz gibi örnek oluşturmaya müsait değil ve farklı yapılandırma ayarları eklemek istiyorsak eğer biraz çaba sarf etmemiz gerecek. Oysa uygulama fabrikalarını kullandığımızda, uygulamamızı bir fonksiyona atayarak birden fazla örneğini oluşturabiliriz.
Devam etmeden önce, uygulama dizinini göstermek istiyorum. Böylece, neyin nerede olduğunu kabaca görebilirsiniz.
projectFolder
├── app
│ ├── __init__.py
│ └── routes
│ ├── admin.py
│ └── main.py
├── requirements.txt
├── wsgi.py
└── settings.py
Bu uygulama dizini yapısı, Demongo’da kullandığım yapının kırpılmış hali. Eğer isterseniz bu linkten proje yapısını detaylı olarak inceleyebilirsiniz.
Uygulama Fabrikası Oluşturma
Şimdi, proje dizinimizin içerisine bir app
klasörü oluşturalım ve içerisine __init__.py
dosyasını aşağıdaki gibi oluşturalım. Burada amaç, app
klasörünün bütün projeyi, bir bütün olarak temsil etmesini sağlamaktır.
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from settings import DefaultConfig
db = SQLAlchemy()
def create_app(configs=DefaultConfig):
app = Flask(__name__)
app.config.from_object(configs)
db.init_app(app)
from app.routes.main import main as main_bp
app.register_blueprint(main_bp, url_prefix="/")
from app.routes.admin import admin as admin_bp
app.register_blueprint(admin_bp, url_prefix="/admin")
return app
Burada gördüğünüzüz gibi, uygulamamızı create_app
fonksiyonu içerisinde oluşturduk ve yapılandırdık. Yapılandırma sırasında default bir config alsa da kullanıcının istediği harici bir config ile çalışabilmesinede olanak sağlamış olduk.
Dikkat etmemiz gereken önemli bir detay ise 13. satırda bulunuyor. SQLAlchemy gibi Flask modüllerini uygulamamıza tanıtmamız için init_app
ile uygulama bağlamına eklememiz gerekiyor. Aksi durumda modülü kullanamayacağız. (Uygulama Bağlamı – Application Context – kavramına farklı bir yazıda değineceğim)
Ayrıca, 15. satırdan itibaren Blueprint ile oluşturduğumuz modülleri projemize dahil ettik. Örneğin, kök dizine (/) gelecek istekleri karşılayacak modülümüze main ismini verdik. Modül içeriği aşağıdaki gibidir.
from flask import Blueprint, render_template, current_app
main = Blueprint("main", __name__)
@main.route("/")
@main.route("/index")
def index():
temp_value = current_app.config["ENV"]
return render_template("views/main/index.html", title="Home")
Gördüğünüz gibi, web sitesinin temel sayfalarını oluşturan modülü bu şekilde geliştirmiş olduk. Admin panelini içeren sayfalarıda benzer şekilde geliştirebilirsiniz. Burada yabancı gelen tek şey muhtemelen 1. ve 9.satırdaki current_app
nesnesidir. Bu nesne, uygulamamızı temsil eder ve uygulamamıza ait bütün özellikleri içerisinde barındırır. Böylece uygulama ait verilere bu nesne aracılığı ile ulaşabiliriz.
Application Config
Uygulamamızda farklı ortamlar için farklı konfigürasyon dosyaları kullanmamız gerekebilir. Bunun için settings.py
dosyasına farklı ortamlar için farklı ayar sınıfları oluşturmamız gerekiyor.
from os import path, environ, getenv
class DefaultConfig(object):
def __init__(self):
self.BASEDIR = path.abspath(path.dirname(__file__))
self.SQLALCHEMY_DATABASE_URI = environ['DATABASE']
self.SQLALCHEMY_TRACK_MODIFICATIONS = False
self.SECRET_KEY = "super_secret_key"
self.ROOT_URL = "http://0.0.0.0:5000"
class ProductionConfig(DefaultConfig):
def __init__(self):
super(ProductionConfig, self).__init__()
self.SQLALCHEMY_DATABASE_URI = environ['DATABASE']
self.ROOT_URL = "https://prodsite.com"
class TestConfig(DefaultConfig):
def __init__(self):
super(ProductionConfig, self).__init__()
self.SQLALCHEMY_DATABASE_URI = environ['DATABASE']
self.ROOT_URL = "https://testsite.com"
Uygulamayı Çalıştırma
Uygulamamızı temel hatları ile geliştirdiğimize göre geliştirme ortamına ayağa kaldırabiliriz. Bunun için terminal üzerinden, proje dizininde flask run
komutunu vermeniz yeterli olacaktır. Böylece proje localde hızlı bir şekilde ayağa kalkacaktır.
~$ export FLASK_ENV=development
~$ flask run
Uygulamayı WSGI Server’a Tanıtma
Projemizi uygulama fabrikası ile oluşturduk. Şimdi uygulamamızı bir WSGI Server ile çalıştırabilmemiz için arayüz dosyası hazırlamamız gerekiyor.
from app import create_app
from settings import ProductionConfig, TestConfig
production_app = create_app(configs=ProductionConfig)
test_app = create_app(configs=TestConfig)
if __name__ == "__main__":
test_app.run()
Gördüğünüz gibi, uygulamamızın farklı ortamlarda çalışacak iki farklı örneğini hızlıca oluşturduk. Şimdi gunicorn yada benzeri bir WSGI Server’a uygulamamızı tanıtmak için wsgi.py
dosyasındaki uygulama örneklerinden birini işaret edebilirsiniz. Hepsi bu kadar.
Uygulama fabrikaların mantığı biraz kafa karıştırıcı olsada doğru kullanımı hayat kurtarır diyebilirim. Daha önce geliştirdiğim Demongo isimli projeyi kullanarak sizlerde Flask ile hızlıca Application Factory Pattern kullanan uygulamalar geliştirebilirsiniz. İyi yapılandırılmış uygulama mimarisi ve ihtiyacınız olan pek çok şeyin içerisinde bulunması size oldukça hız katacaktır diyebilirim.
Demongo: https://github.com/emregeldegul/demongo
Faydalı olması dileklerim ile, iyi çalışmalar.
yapıyorsun bu işi :)) eline sağlık yunus emre başarılı olmuş
Çok teşekkür ediyorum Ercan =)
Akıcı bir makale olmuş. Teşekkürler.
Teşekkürler Oktay.