구성에 대한 규칙을 사용하여 Flask 프로젝트 구조화

사람들이 나에게 초보자 파이썬 개발자가 새로운 웹 프로젝트를 시작하기 위해 Flask 또는 Django 중 무엇을 선택해야 하는지 물을 때, 다른 모든 것이 동일하다면 나는 항상 Django를 추천합니다.

Flask와 달리 Django는 독단적입니다. 즉, Flask에서 선택해야 할 때마다 Django가 답을 제공합니다. 그 중에서도 Django는 즉시 사용할 수 있는 실용적인 프로젝트 구조를 설명합니다.

Django를 사용하면 프로젝트를 애플리케이션으로 분할할 수 있습니다. 응용 프로그램 자체에는 잘 정의된 구조가 있습니다. views.py, models.py 등이 있습니다. 디자인을 유지하고 시행하는 것은 convention over configuration 접근법입니다. 코드를 잘 알려진 특정 위치에 넣으면 프레임워크가 이를 발견합니다.

Flask는 그런 것을 강요하지 않습니다. 단일 파일로 시작할 수 있습니다. 응용 프로그램이 커지면 응용 프로그램 구조를 제공하는 것은 귀하에게 달려 있습니다. 결과적으로 앱은 유지 관리할 수 없는 혼란으로 빠르게 변할 수 있습니다.

비독점적 원칙에 따라 공식 Flask 문서는 개발자가 결정할 수 있도록 남겨 둡니다. 챕터Larger ApplicationsModular Applications with Blueprints는 주제를 완전히 다루지 않습니다. 격차를 좁히기 위해 사람들은 자신만의 지침을 만들었습니다. 다양한 변형과 ​​제안을 찾기 위한 Google "플라스크 프로젝트 구조". 예를 들어, 기념비적인 Flask Mega-tutorial에는 장a better application structure이 있습니다.

Flask 솔루션에 대해 저를 괴롭히는 것은 규칙에 대한 지원이 부족하다는 것입니다. 저 같으면 모든 패키지와 청사진에서 모든 것을 수동으로 가져와 구성하는 기능app()이 있습니다. 낯익은데? 더럽다.

# file: myproject/app.py

def app():
    from myproject.users.controller import blueprint as users_blueprint
    from myproject.projects.controller import blueprint as projects_blueprint
    ...
    # Initialize extensions
    db.init_app(flask_app)

    ...
    # Register blueprints
    flask_app.register_blueprint(users_blueprint)
    flask_app.register_blueprint(projects_blueprint)
    ...

모든 내선에 대해 init_app로 전화하십시오. 잘 정의된 구조를 가진 모든 애플리케이션에 대해 가져오기 및 등록이 포함된 몇 줄을 추가하여 춤을 춥니다.

어떻게든 문제를 해결하기 위해 Python 패키지roman-discovery를 생성했습니다. 패키지를 사용하면 응용 프로그램의 규칙을 선언적으로 정의하고 discover() 함수를 실행하여 해당 규칙을 적용할 수 있습니다. Flask에만 국한된 것은 아니지만 주로 Flask를 염두에 두고 만들었습니다.

예를 들어 myproject/<app>/controllers.py에 모든 청사진을 저장한다고 가정하면 자동으로 모두 등록할 수 있습니다.

from flask import Blueprint
from roman_discovery import ObjectRule, discover
from roman_discovery.matchers import MatchByPattern, MatchByType

blueprint_loader = ObjectRule(
    name="Flask blueprints loader",
    module_matches=MatchByPattern(["myproject.*.controllers"]),
    object_matches=MatchByType(Blueprint),
    object_action=flask_app.register_blueprint,
)

discover(import_path="myproject", rules=[blueprint_loader])

영감의 원천으로 사용할 수 있는 roman_discovery.flask 모듈이 있습니다. 제 규칙을 적용해도 상관없다면 그대로 사용하세요.

from roman_disovery.flask import discover_flask

app = Flask(__name__)
app.config.from_object("myproject.config")
discover_flask("myproject", app)

최신 행은 다음을 수행합니다.
  • myproject/*/controllers.pymyproject/*/controllers/*.py를 스캔하여 청사진을 찾아 Flask 응용 프로그램에 첨부합니다.
  • myproject/*/models.pymyproject/*/models/*.py의 모든 파일을 가져오면 flask-migrate가 모든 SQLAlchemy 모델을 찾아 마이그레이션을 생성할 수 있습니다.
  • myproject/*/cli.pymyproject/*/cli/*.py의 모든 파일을 스캔하여 flask.cli.AppGroup 인스턴스를 찾아 Flask의 CLI에 연결합니다.
  • 최상위 수준myproject/services.py을 스캔하고 init_app() 메서드가 있는 모든 인스턴스를 찾은 다음 각각에 대해 obj.init_app(app=app)를 호출합니다.

  • 아직 새롭고 문서, 예제 및 테스트가 부족하지만 이미 도움이 되었기를 바랍니다.

    roman-discovery on GitHub 을 따라 패키지에 일반적이지 않은 "roman-"접두어가 있는 이유도 알아보십시오.


    이만쿨로프 / 디커버리


    Python 프로젝트에서 패키지 및 클래스 검색






    발견


    마이크로 프레임워크 초기화 문제


    마이크로 프레임워크 기반 프로젝트는 작지만 깨끗합니다. 내가 본 모든 마이크로 프레임워크 코드베이스는 프로젝트 초기화에 엉망이 있습니다. 시간이 지남에 따라 create_app()는 임시 설정, 기능 내 가져오기 및 플러그인 초기화로 채워집니다.
    예를 들어 official Flask documentationFlask Mega-Tutorial 에서 제안된 애플리케이션 팩토리 패턴은 이 접근 방식을 합법화합니다.create_app()의 특성상 open-closed principle이 들어갈 자리가 없습니다. 새 플러그인, 새 청사진 또는 새 패키지를 추가할 때마다 이 모듈을 업데이트합니다.
    # myproject/__ini__.py
    #
    # A common Flask application. The code is based on the Flask Mega-Tutorial.
    def create_app(config_class=Config):
        app = Flask(__name__)
        app.config.from_object(config_class)
    
        db.init_app(app)
        migrate.init_app(app, db)
        login.init_app(app)
        mail.init_app(app)
        bootstrap



    View on GitHub

    좋은 웹페이지 즐겨찾기