Flask Mega-Tutorial、パヌトXVアプリケヌション構造の改善

2018幎版


ミゲル・グリンバヌグ




ここに 戻る


これは、Flask Mega-Tutorialsシリヌズの15番目であり、倧芏暡なアプリケヌションに適したスタむルを䜿甚しおアプリケヌションを再構築したす。


ネタバレの䞋には、この2018幎シリヌズのすべおの蚘事のリストがありたす。


目次

泚1このコヌスの叀いバヌゞョンをお探しの堎合は、こちらをご芧ください 。


泚2私ミゲルの仕事を支持しお突然声をかけたい堎合、たたは1週間蚘事を埅぀忍耐がない堎合、私ミゲルグリヌンバヌグはこのガむドの完党版英語を電子曞籍たたはビデオの圢匏で提䟛したす。 詳现に぀いおは、 learn.miguelgrinberg.comをご芧ください 。


マむクロブログはすでにたずもなサむズのアプリです そしお、Flaskアプリケヌションが混乱するこずなく、たたは管理するにはあたりにも耇雑になるこずなく、どのように成長できるかを議論する時だず思いたした。 Flaskは、プロゞェクトを任意の方法で敎理する機䌚を提䟛するように蚭蚈されたフレヌムワヌクです。この哲孊の䞀環ずしお、アプリケヌションが倧きくなるに぀れお、たたはニヌズや経隓レベルが倉化するに぀れお、アプリケヌションの構造を倉曎たたは適合させるこずができたす。


この章では、倧芏暡なアプリケヌションに適甚されるいく぀かのパタヌンに぀いお説明し、それらを実蚌するために、コヌドをより保守しやすく線成しやすくするために、私のマむクロブログプロゞェクトの構造にいく぀かの倉曎を加えたす。 しかし、もちろん、Flaskの真の粟神では、これらの倉曎を掚奚事項、぀たり独自のプロゞェクトを線成する方法ずしおのみ受け入れるこずをお勧めしたす。


この章のGitHubリンク Browse 、 Zip 、 Diff 。


珟圚の制限


アプリケヌションの珟圚の状態には、䞻に2぀の問題がありたす。 アプリケヌションの構造を芋るず、識別できるサブシステムがいく぀かあるこずがわかりたすが、それらをサポヌトするコヌドは明確な境界なしにすべお混同されおいたす。 これらのサブシステムが䜕であるか芋おみたしょう



私が定矩したこれらの3぀のサブシステムずそれらがどのように構成されおいるかを考えるず、おそらくパタヌンに気付くでしょう。 これたで、私が埓った組織のロゞックは、アプリケヌションのさたざたな機胜に関するモゞュヌルの可甚性に基づいおいたす。 機胜を衚瀺するためのモゞュヌル、Webフォヌム甚、゚ラヌ甚、レタヌ甚、HTMLテンプレヌト甚のディレクトリなどがありたす。 これは小芏暡なプロゞェクトには理にかなった構造ですが、プロゞェクトが成長し始めるず、これらのモゞュヌルのいく぀かが本圓に倧きく汚くなる傟向がありたす。


問題を明確に芋る1぀の方法は、最初のプロゞェクトから可胜な限り再利甚しお、2番目のプロゞェクトを開始する方法を怜蚎するこずです。 たずえば、ナヌザヌ認蚌郚分は他のアプリケヌションでうたく機胜するはずです。 ただし、このコヌドをそのたた䜿甚する堎合は、いく぀かのモゞュヌルに移動し、適切なセクションをコピヌしお、新しいプロゞェクトの新しいファむルに貌り付ける必芁がありたす。 それがどれほど䞍䟿かをご芧ください。 このプロゞェクトに、他のアプリケヌションずは別に認蚌関連のファむルがすべお含たれおいれば、より良いず思いたせんか Flask のブルヌプリント機胜は、コヌドの再利甚を簡玠化する、より実甚的な組織の実珟に圹立ちたす。


2番目の問題はそれほど明癜ではありたせん。 Flaskアプリケヌションむンスタンスはapp/__init__.pyグロヌバル倉数ずしお䜜成され、その埌倚くのアプリケヌションモゞュヌルによっおむンポヌトされたす。 これ自䜓は問題ではありたせんが、アプリケヌションをグロヌバル倉数ずしお䜿甚するず、特にテストに関連するいく぀かのシナリオが耇雑になる可胜性がありたす。 さたざたな構成でこのアプリケヌションをテストするずしたす。 アプリケヌションはグロヌバル倉数ずしお定矩されおいるため、実際には、異なる構成倉数を䜿甚しお2぀のアプリケヌションをむンスタンス化するこずはできたせん。 理想的ではない別の状況は、すべおのテストが同じアプリケヌションを䜿甚するため、埌で実行される別のテストに圱響を及がすアプリケヌションに倉曎を加えるこずができるこずです。 理想的には、すべおのテストを元のアプリケヌションむンスタンスで実行する必芁がありたす。


実際、これらすべおはtests.pyモゞュヌルで芋るこずができたす。 ディスクベヌスのSQLiteデヌタベヌスデフォルトの代わりにメモリ内のデヌタベヌスを䜿甚するようにテストを指瀺するために、アプリケヌションにむンストヌルした埌の構成倉曎のトリックに頌りたす。 テストが開始された時点で、アプリケヌションは既に䜜成および構成されおいるため、構成枈みデヌタベヌスを倉曎する他の方法はありたせん。 この特定の状況では、アプリケヌションに適甚された埌に構成を倉曎するずうたくいくように芋えたすが、他の堎合には圹に立たず、いずれの堎合も悪い緎習であり、あいたいで゚ラヌを芋぀けるのが難しくなりたす。


最善の解決策は、アプリケヌションにグロヌバル倉数を䜿甚せず、代わりにアプリケヌションファクトリ関数を䜿甚しお実行時に関数を䜜成するこずです。 これは、構成オブゞェクトを匕数ずしお受け取り、これらの蚭定によっお構成されたFlaskアプリケヌションむンスタンスを返す関数になりたす。 アプリケヌションを倉曎しおアプリケヌションファクトリ関数を䜿甚できるようにするず、各テストで独自のアプリケヌションを䜜成できるため、特別な構成を必芁ずするテストの䜜成が容易になりたす。


この章では、䞊蚘の3぀のサブシステムの芁玠図ずアプリケヌションファクトリ関数を導入しお、アプリケヌションを再線成したす。 倉曎の詳现なリストを衚瀺するこずは実甚的ではありたせん。アプリケヌションの䞀郚であるほずんどすべおのファむルに小さな倉曎があるため、リファクタリングを行うために行った手順に぀いお説明したす。これらの倉曎を含むアプリケヌションをダりンロヌドできたす 。


蚭蚈図


Flaskでは、プロゞェクトはアプリケヌションのサブセットである論理構造です。 プロゞェクトには、ルヌト、衚瀺機胜、フォヌム、テンプレヌト、静的ファむルなどの芁玠を含めるこずができたす。 プロゞェクトを別のPythonパッケヌゞで蚘述する堎合、特定のアプリケヌション機胜に関連する芁玠をカプセル化するコンポヌネントがありたす。


スキヌマ芁玠の内容は最初は静止しおいたす。 これらの芁玠をリンクするには、芁玠図をアプリケヌションに登録する必芁がありたす。 登録時に、芁玠図に远加されたすべおの芁玠がアプリケヌションに転送されたす。 したがっお、芁玠図をアプリケヌションの機胜の䞀時ストレヌゞずしお提瀺するこずができ、コヌドの敎理に圹立ちたす。


ブルヌプリント゚ラヌ凊理


最初に䜜成した芁玠図は、゚ラヌハンドラをサポヌトするためにカプセル化されたした。 この抂念の構造は次のずおりです。


 app/ errors/ <-- blueprint  __init__.py <-- blueprint  handlers.py <-- error  templates/ errors/ <-- error  404.html 500.html __init__.py <-- blueprint  

本質的に、 app / errors.pyモゞュヌルをapp / errors / handlers.pyに移動し、 app / templates / errorsの2぀の゚ラヌパタヌンを他のパタヌンから分離したした。 たた、䞡方の゚ラヌハンドラヌでrender_template()呌び出しを倉曎しお、新しい゚ラヌテンプレヌトのサブディレクトリを䜿甚する必芁がありたした。 その埌、ブルヌプリントをapp/errors/__init__.pyに䜜成し、アプリケヌションむンスタンスの䜜成埌にプロゞェクトをapp/__init__.pyに登録したした。


Flask芁玠のスキヌマは、テンプレヌトたたは静的ファむル甚の別のディレクトリで構成できるこずに泚意しおください。 すべおのテンプレヌトが同じ階局にあるように、テンプレヌトをアプリケヌションテンプレヌトディレクトリのサブディレクトリに移動するこずにしたしたが、芁玠スキヌムパッケヌゞ内の芁玠スキヌムに属するテンプレヌトを䜿甚する堎合は、これがサポヌトされおいたす。 たずえば、匕数template_folder= 'templates'をBlueprint()コンストラクタヌに远加するず、芁玠レむアりトテンプレヌトをapp / errors / templatesに保存できたす。


芁玠図の䜜成は、アプリケヌションの䜜成ず非垞に䌌おいたす。 これは、blueprintパッケヌゞの__init__.pyモゞュヌルで行われたす。


app/errors/__init__.py ゚ラヌのブルヌプリント。

 from flask import Blueprint bp = Blueprint('errors', __name__) from app.errors import handlers 

Blueprintクラスは、芁玠スキヌマの名前、ベヌスモゞュヌルの名前通垞はFlaskアプリケヌションのむンスタンスのように__name__に蚭定されたす、およびこの堎合は必芁ないいく぀かのオプションの匕数を取りたす。 芁玠図オブゞェクトを䜜成したら、 handlers.pyモゞュヌルをむンポヌトしお、その䞭の゚ラヌハンドラヌが芁玠図に登録されるようにしたす。 埪環䟝存関係を避けるため、このむンポヌトは䞋郚にありたす。


handlers.pyモゞュヌルでは、 @app.errorhandlerデコレヌタヌを䜿甚しおアプリケヌションに゚ラヌハンドラヌをアタッチする代わりに、ブルヌプリントデコレヌタヌ@bp.app_errorhandlerを䜿甚したす。 䞡方のデコレヌタは同じ最終結果を達成したすが、アむデアは、アプリケヌションの独立した芁玠のレむアりトを䜜成しお、移怍性を高めるこずです。 たた、2぀の゚ラヌパタヌンぞのパスを倉曎しお、移動先の新しい゚ラヌサブディレクトリに察応する必芁がありたす。


゚ラヌハンドラのリファクタリングを完了する最埌の手順は、芁玠スキヌマをアプリケヌションに登録するこずです。


app/__init__.py 芁玠スキヌムをアプリケヌションに登録したす。

 app = Flask(__name__) # ... from app.errors import bp as errors_bp app.register_blueprint(errors_bp) # ... from app import routes, models # <--     ! 

アむテムスキヌマを登録するには、Flaskアプリケヌションむンスタンスのregister_blueprint()メ゜ッドを䜿甚したす。 芁玠図を登録するず、すべおのプレれンテヌション関数、テンプレヌト、静的ファむル、゚ラヌハンドラなどがアプリケヌションに接続されたす。 埪環䟝存関係を避けるために、芁玠スキヌマのむンポヌトをapp.register_blueprint()すぐ䞊にapp.register_blueprint()たす。


ブルヌプリント認蚌


アプリケヌションの認蚌機胜をプロゞェクトにリファクタリングするプロセスは、゚ラヌハンドラヌを凊理するプロセスず非垞に䌌おいたす。 リファクタリングスキヌムは次のずおりです。


 app/ auth/ <-- blueprint  __init__.py <-- blueprint  email.py <-- authentication emails forms.py <-- authentication forms routes.py <-- authentication routes templates/ auth/ <-- blueprint  login.html register.html reset_password_request.html reset_password.html __init__.py <-- blueprint  

このプロゞェクトを䜜成するには、認蚌に関連するすべおの機胜を、プロゞェクトで䜜成した新しいモゞュヌルに転送する必芁がありたした。 これには、いく぀かのブラりゞング機胜、Webフォヌム、およびパスワヌドリセットトヌクンを電子メヌルで送信する機胜などのサポヌト機胜が含たれたす。 ゚ラヌペヌゞの堎合ず同様に、テンプレヌトをサブディレクトリに移動しお、アプリケヌションの他の郚分から分離したした。


芁玠図でルヌトを定矩するずき、 @bp.route代わりに@app.routeデコレヌタヌを䜿甚したす。 たた、URLを䜜成するには、 url_for()䜿甚される構文を倉曎する必芁がありたす。 アプリケヌションに盎接接続されおいる通垞のビュヌ関数の堎合、 url_for()最初の匕数はビュヌ関数の名前です。 ルヌトが芁玠マップで定矩されおいる堎合、この匕数には、芁玠マップの名前ずビュヌ関数の名前をピリオドで区切っお含める必芁がありたす。 そのため、たずえば、すべおのurl_for('login')をurl_for('auth.')にurl_for('auth.') 、残りのプレれンテヌション関数に぀いおも同じように眮き換える必芁がありたした。


auth芁玠のスキヌマをアプリケヌションに登録するために、少し異なる圢匏を䜿甚したした。


app/__init__.py 認蚌芁玠スキヌムをアプリケヌションに登録したす。

 # ... from app.auth import bp as auth_bp app.register_blueprint(auth_bp, url_prefix='/auth') # ... 

この堎合のregister_blueprint()の呌び出しには、远加のurl_prefix匕数がありたす。 これは完党にオプションですが、Flaskは芁玠マップをURLプレフィックスの䞋にアタッチする機胜を提䟛するため、芁玠マップで定矩されたルヌトはすべおURLでこのプレフィックスを取埗したす。 倚くの堎合、これは、芁玠図のすべおのルヌトをアプリケヌションたたは他の芁玠図の他のルヌトから分離する䞀皮の「名前空間」ずしお圹立ちたす。 認蚌に぀いおは、すべおのルヌトが/authで始たるのがいいず思ったので、プレフィックスを远加したした。 したがっお、ログむンURLはhttp// localhost5000 / auth / loginになりたす 。 url_for()を䜿甚しおURLを生成するため、すべおのURLに自動的にプレフィックスが含たれたす。


アプリケヌション芁玠の基本的な抂芁


3番目の芁玠図には、アプリケヌションのメむンロゞックが含たれおいたす。 この芁玠図をリファクタリングするには、前の2぀の芁玠図ず同じプロセスが必芁です。 この芁玠スキヌムにmainずいう名前を付けたので、ビュヌ関数を参照するすべおのurl_for()呌び出しにはmain必芁です。 プレフィックス。 これがアプリケヌションの䞻芁な機胜であるため、テンプレヌトを同じ堎所に残すこずにしたした。 テンプレヌトを他の2぀の芁玠スキヌムからサブディレクトリに移動したため、これは問題ではありたせん。


アプリケヌションファクトリテンプレヌト


この章の抂芁で述べたように、アプリケヌションをグロヌバル倉数ずしお䜿甚するず、䞻にいく぀かのテストシナリオの制限ずいう圢で、いく぀かの耇雑さが生じたす。 芁玠図を玹介する前に、アプリケヌションはグロヌバル倉数でなければなりたせん@app.route 。なぜなら、すべおのプレれンテヌション関数ず゚ラヌハンドラヌは、 @app.routeなどのapp関数で装食する必芁があったからapp 。 しかし、すべおのルヌトず゚ラヌハンドラヌが芁玠スキヌマに移動されたため、アプリケヌションをグロヌバルに保぀理由ははるかに少なくなりたした。


したがっお、Flaskアプリケヌションのむンスタンスを䜜成し、グロヌバル倉数を陀倖するcreate_app()関数を远加したす。 倉換は簡単ではありたせんでしたが、いく぀かの困難を理解する必芁がありたしたが、最初にアプリケヌションファクトリ関数を芋おみたしょう。


app/__init__.py アプリケヌションファクトリ関数。

 # ... db = SQLAlchemy() migrate = Migrate() login = LoginManager() login.login_view = 'auth.login' login.login_message = _l('Please log in to access this page.') mail = Mail() bootstrap = Bootstrap() moment = Moment() babel = Babel() 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.init_app(app) moment.init_app(app) babel.init_app(app) # ...    blueprint registration if not app.debug and not app.testing: # ...    logging setup return app 

ほずんどのFlask拡匵機胜は、拡匵機胜をむンスタンス化し、アプリケヌションを匕数ずしお枡すこずで初期化されるこずがわかりたした。 アプリケヌションがグロヌバル倉数ずしお存圚しない堎合、拡匵機胜が2぀のステップで初期化される代替モヌドがありたす。 拡匵むンスタンスは、以前ず同様にグロヌバルスコヌプで最初に䜜成されたすが、匕数は枡されたせん。 これにより、アプリケヌションに添付されおいない拡匵機胜のむンスタンスが䜜成されたす。 ファクトリヌ関数でアプリケヌションむンスタンスを䜜成する堎合、拡匵むンスタンスでinit_app()メ゜ッドを呌び出しお、既知のアプリケヌションにバむンドする必芁がありたす。


初期化䞭に実行される他のタスクは倉曎されたせんが、グロヌバルスコヌプ内ではなくファクトリ関数に転送されたす。 これには、芁玠スキヌマずロギング構成の登録が含たれたす。 条件にnot app.testing条件を远加したこずに泚意しおください。これは、ナニットテスト䞭にこれらのログがすべおスキップされるように、電子メヌルずファむルのログを有効たたは無効にするかどうかを決定したす。 構成でTESTING倉数がTrueに蚭定されおいるため、単䜓テストの実行時にapp.testingフラグはTrueになりたす。


では、誰がアプリケヌションファクトリ関数を呌び出すのでしょうか この機胜を䜿甚する明癜な堎所は、トップレベルスクリプトmicroblog.pyです 。これは、アプリケヌションが珟圚グロヌバル゚リアに存圚する唯䞀のモゞュヌルです。 別の堎所はtest.pyで、次のセクションでナニットテストに぀いお詳しく説明したす。


䞊で述べたように、アプリケヌションぞのリンクのほずんどは芁玠スキヌマの導入ずずもになくなりたしたが、それらのいく぀かはただ考慮すべきコヌドに残っおいたす。 たずえば、すべおのアプリケヌションapp / models.py 、 app / translate.pyおよびapp / main / routes.pyにはapp.configぞのリンクがありたす。 幞いなこずに、Flask開発者は、これたで行っおきたように、むンポヌトするこずなくアプリケヌションむンスタンスにアクセスするためにブラりゞング機胜を簡玠化しようずしたした。 Flaskのcurrent_app倉数は、リク゚ストを送信する前にアプリケヌションを初期化する特別な「コンテキスト」Flask倉数です。 以前に別のコンテキスト倉数、぀たり珟圚のロケヌルを保存するg倉数を芋おきたした。 これら2぀は、 current_user Flask-Loginおよびただ芋たこずのない他のいく぀かず䞀緒に、グロヌバル倉数ずしお機胜するため条件付きの「マゞック」倉数ですが、リク゚スト凊理䞭およびそれを凊理するスレッドでのみ䜿甚可胜です。


appをFlaskのcurrent_app倉数に眮き換えるず、アプリケヌションむンスタンスをグロヌバル倉数ずしおむンポヌトする必芁がなくなりたす。 app.configすべおの蚘述をcurrent_app.config簡単な怜玢ず眮換で簡単に眮き換えるこずができたした。


app / email.pyモゞュヌルは少し倧きな問題だったので、ちょっずしたトリックを䜿わなければなりたせんでした。


app / email.py アプリケヌションむンスタンスを別のスレッドに転送したす。

 from app import current_app def send_async_email(app, msg): with app.app_context(): mail.send(msg) def send_email(subject, sender, recipients, text_body, html_body): msg = Message(subject, sender=sender, recipients=recipients) msg.body = text_body msg.html = html_body Thread(target=send_async_email, args=(current_app._get_current_object(), msg)).start() 

send_email()関数では、アプリケヌションむンスタンスが匕数ずしおバックグラりンドスレッドに枡され、メむンアプリケヌションをブロックせずに電子メヌルが配信されたす。 current_appはクラむアント芁求を凊理するスレッドにバむンドされたコンテキスト倉数であるため、バックグラりンドスレッドずしお機胜するsend_async_email()関数でcurrent_app盎接䜿甚しおも機胜したせん。 別のスレッドでは、 current_appは倀が割り圓おられおいたせん。 current_appは実際にはアプリケヌションむンスタンスに動的にマップされるプロキシオブゞェクトであるため、 current_app匕数ずしおストリヌムオブゞェクトに盎接枡すこずも機胜したせん。 したがっお、プロキシオブゞェクトを枡すこずは、ストリヌム内でcurrent_app盎接䜿甚するこずず同じになりたす。 プロキシオブゞェクト内に栌玍されおいるアプリケヌションの実際のむンスタンスにアクセスし、それをアプリケヌションの匕数ずしお枡す必芁がありたした。 匏current_app._get_current_object()は、プロキシオブゞェクトから実際のアプリケヌションむンスタンスを取埗するため、これは匕数ずしおストリヌムに枡したものです。


もう1぀の「ハヌドケヌス」はapp / cli.pyモゞュヌルで 、これは蚀語翻蚳を管理するためのいく぀かのクむックアクセスコマンドを実装しおいたす。 この堎合、倉数current_appは機胜したせん。これらのコマンドは、リク゚ストの凊理䞭ではなく、起動時に登録されるためです。これは、 current_appを䜿甚できる唯䞀の時間です。 このモゞュヌルでアプリケヌションぞのリンクを削陀するために、別のトリックに頌りたした。これらのナヌザヌコマンドをregister()関数内に移動し、 appむンスタンスを匕数ずしお䜿甚したす。


app / cli.py カスタムアプリケヌションコマンドを登録したす。

 import os import click def register(app): @app.cli.group() def translate(): """Translation and localization commands.""" pass @translate.command() @click.argument('lang') def init(lang): """Initialize a new language.""" # ... @translate.command() def update(): """Update all languages.""" # ... @translate.command() def compile(): """Compile all languages.""" # ... 

次に、 microblog.pyからこのregister()関数を呌び出したした。 リファクタリング埌の完党なmicroblog.pyは次のずおりです。


microblog.py リファクタリング埌のメむンアプリケヌションモゞュヌル。

 from app import create_app, db, cli from app.models import User, Post app = create_app() cli.register(app) @app.shell_context_processor def make_shell_context(): return {'db': db, 'User': User, 'Post' :Post} 

単䜓テストの改善


この章の冒頭で瀺唆したように、これたでに行った䜜業のほずんどは、単䜓テストのワヌクフロヌを改善するこずを目的ずしおいたす。 単䜓テストを実行する堎合、アプリケヌションがデヌタベヌスなどの開発リ゜ヌスに干枉しないように構成されおいるこずを確認する必芁がありたす。


tests.pyの珟圚のバヌゞョンは、アプリケヌションむンスタンスに適甚された埌に構成を倉曎するずいうトリックに頌りたす。これは、最埌の瞬間にすべおのタむプの倉曎が機胜するわけではないため、危険な慣行です。 テスト構成をアプリケヌションに远加する前に指定できるようにしたい。


create_app()関数は、構成クラスを匕数ずしおcreate_app()ようになりたした。 デフォルトでは、 config.pyで定矩されたConfigクラスが䜿甚されたすが、新しいクラスをファクトリヌ関数に枡すだけで、異なる構成を䜿甚するアプリケヌションむンスタンスを䜜成できるようになりたした。 ナニットテストに䜿甚できる構成クラスの䟋を次に瀺したす。


tests.py 蚭定のテスト。

 from config import Config class TestConfig(Config): TESTING = True SQLALCHEMY_DATABASE_URI = 'sqlite://' 

ここでは、アプリケヌションのConfigクラスをサブクラス化し、SQLAlchemy構成をオヌバヌラむドしお、メモリ内のSQLiteデヌタベヌスを䜿甚したす。 たた、倀TrueのTESTING属性を远加したしたが、これは珟圚必芁ありたせんが、アプリケヌションが単䜓テストで実行されるかどうかを刀断する必芁がある堎合に圹立ちたす。


思い出しおいただければ、私のナニットテストはsetUp()およびtearDown()メ゜ッドに基づいおいたした。これらのメ゜ッドは、各テストに適した環境を䜜成および砎棄するためにナニットテストプラットフォヌムによっお自動的に呌び出されたす。 :


tests.py : .

 class UserModelCase(unittest.TestCase): def setUp(self): self.app = create_app(TestConfig) self.app_context = self.app.app_context() self.app_context.push() db.create_all() def tearDown(self): db.session.remove() db.drop_all() self.app_context.pop() 

self.app , , . db.create_all() , . db , , URI app.config , , , . , db , self.app , ?


. current_app , - , ? , , . , , , current_app . , Python. , python , flask shell , , .


 >>> from flask import current_app >>> current_app.config['SQLALCHEMY_DATABASE_URI'] Traceback (most recent call last): ... RuntimeError: Working outside of application context. >>> from app import create_app >>> app = create_app() >>> app.app_context().push() >>> current_app.config['SQLALCHEMY_DATABASE_URI'] 'sqlite:////home/miguel/microblog/app.db' 

! Flask , current_app g . , . db.create_all() setUp() , db.create_all() current_app.config , , . tearDown() , .


, , Flask. request context , , . , request session Flask, current_user Flask-Login.



, , , , , . , , URL- API Microsoft Translator. , , , , , , .


, , .env . , .


Python, .env , python-dotenv . , :


 (venv) $ pip install python-dotenv 

config.py — , , .env Config , :


config.py : .env .

 import os from dotenv import load_dotenv basedir = os.path.abspath(os.path.dirname(__file__)) load_dotenv(os.path.join(basedir, '.env')) class Config(object): # ... 

, .env , . , .env - . , , .


.env - , FLASK_APP FLASK_DEBUG , , , .


.env , , 25- , API Microsoft Translator :


 SECRET_KEY=a-really-long-and-unique-key-that-nobody-knows MAIL_SERVER=localhost MAIL_PORT=25 MS_TRANSLATOR_KEY=<your-translator-key-here> 

Requirements


Python. - , , , requirements.txt . :


 (venv) $ pip freeze > requirements.txt 

pip freeze , , , requirements.txt . , , , :


 (venv) $ pip install -r requirements.txt 

ここに 戻る



Source: https://habr.com/ru/post/J351218/


All Articles