何のフラスコ?

kdpv

実際、これはwtformsからの写真ですが、何らかの理由で私のgimpが起動しません。







私はこの記事をバーで書いています。 私は本当に冷やしたいのですが、バーテンダーは丸い目で私を見て、水ギセルマンは微笑んで頭を振っただけです。







一度、彼らは私に尋ねた:フラスコの何が問題なのか? それから、このかわいいフレームワークに完全に満足しました。 彼としばらく仕事をした後、私は考えていることをすべて作業用のスラックスで書きました。 実際、私は親切でふわふわですが、wtf?!







アーミンの作品の大ファンであることは注目に値します。 彼のパッケージは私のプロジェクトの多くで使用されています。 彼はまた、Pythonコミュニティのすばらしい破片です。 そしてそれは良いことです。







フラスコ



Flaskは非常にクールなスタンドアロンプ​​ロジェクトのラッパーです。 ジャンガと比較する人もいます。 なんで?







2つのポイントですべてのフラスコの問題を説明しようとすると:







  1. 輸入品
  2. リクエストコンテキスト


それだけです さらに読むことはできません。 しかし、まだ明確でない場合は、さらにスクロールします。







設計図



ジャングルですべてのアプリケーションがINSTALLED_APPS



で接続されている場合、ブループリントの概念がblueprints



使用されます。 ある種類のアプリケーションと1つのボトル内の個別の名前空間URL:







 from flask import Flask from yourapplication.simple_page import simple_page app = Flask(__name__) app.register_blueprint(simple_page, end_point='/simple_page')
      
      





さらに、 url_for('simple_page.index')



ようなURLをルーティングできます。







ネスティング



しかし、彼女はそうではありません。 それを取得してネストされた名前空間を作成することはできません。 ネットワーク上で「解決策」を見つけることができますが、ここでは箱入りフラスコのみを検討します。何でも書くことができるからです。







輸入品



本番コードでこれを行う場合:







 if foo == 3: do_stuff(foo)
      
      





世界のどこかで私は悲しいです! 私の世話をして、設定に持って行ってください。







 from myapp import app class Foo(FlaskForm): choices = SelectField(choices=app.conf.FOO_CHOICES)
      
      





概念的に。 しかし、それは機能しません。 数行前に戻ったので、パッケージをmyapp



インポートし、そこで永遠に予約しました。







待って、抜け道があるに違いない! うん!







 from flask import current_app
      
      





そして、それは機能しません。 current_app



はリクエストコンテキストでのみ使用できるためです!







-ついにアプリケーション設定ファイルに持ち出し、病気のやつだ! -聴衆からの声。

-そして、どうすればそれらをprodまたはtestに置き換えることができますか?







ちなみに、このケースには専用のバッテリーがあります。

django.conf.settings



がリクエストのコンテキストでのみ利用できる素晴らしい不思議な世界を想像してみてください!







flask.g



同じことについて冗談を言わざるを得ません。 そして最も重要なことは、あなたは彼女を探す必要はありません、彼女は常にここにいる: flask.g



。 バダブーム!

だからこそ、アーミンは私のアイドルです!







必要なものをすべて転送できます:







 @app.before_request def before_request(): g.locale = get_locale() g.foo = foo
      
      





ただし、これは他の魔法のフラスコオブジェクトのように、リクエストのコンテキストでのみ機能します。







ルーティングURLとそのメソッド



私のサイトにはURL があります







 bp.add_url_rule('/api/v1/', view_func=ApiView.as_view('api_view')) ... bp.add_url_rule('/<path:path>/', view_func=PageView.as_view('page_view'))
      
      





ApiView



処理するメソッドはPOST



のみです。 GET



を要求するとどうなりますか? ええ、404。彼女は第二の見解を提供します。

NOT ALLOWED



を取得するにNOT ALLOWED



で明示的に405を返す必要があります!







よくある質問、何が悪いのですか?







ステーキ!



A.ちょっと待ってください。 これは私のためです。 オムオムオムオム。







フラスコ-wtf。 CSRF



おお 1つのビューで検証を無効にする必要があるとしましょう。







 @app.route('/foo', methods=('GET', 'POST')) @csrf.exempt def my_handler(): # ... return 'ok'
      
      





したがって、 app



が必要app



。 インポートについて覚えていますか? 私たちは抜け道を探しています。







 def exempt(self, view): ... if isinstance(view, string_types): view_location = view else: view_location = '.'.join((view.__module__, view.__name__)) self._exempt_views.add(view_location) return view
      
      





やった! パスをビューに渡すことができます(2週間前にリリースされたバージョンで)! 私達は試みます:







 csrf.exempt('website.apps.typus_web.views.ApiView')
      
      





動作しません。 実際(この表現は嫌いです)、 ApiView.as_view('api_view')



を呼び出したときにビューの名前を変更しました。







 csrf.exempt('website.apps.typus_web.views.api_view')
      
      





そして、そこに存在しないオブジェクトへのパスを示すのは「すべて同じ」です。 動作します! 動作しません。







理由を知っていますか? フォームだから。 彼女はビューについて何も知りません。







 class ApiForm(ViewForm): ... class Meta(ViewForm.Meta): csrf = False
      
      





今では動作します。







url_for()



あなたがこれをしたいとしましょう:







 NAVIGATION = ( (url_for('flatpages:index'), _('Home page')), )
      
      





忘れて。 コンテキスト外は機能しません。 あなたはおそらくあなたの怠zyなオブジェクトを作ることができます、最後に、ジャンでそれはすぐに現れませんでした。







フラスコ試験



テストを支援するために設計された作品。 たとえば、テンプレートに渡されるコンテキストを調べることができます。 そして試してみましょう:







 AssertionError: Popped wrong request context.
      
      





痛い。 何かがおかしかった。 知ってる? 私も知りません

実際(この表現は嫌いです)、オーバーライドしなかったメソッドの1つでNotImplementedError



NotImplementedError



ました。 しかし、ポイントは、あなたがテストを落とすとき、あなたはその理由を決して理解しないということです。







その他



フラスコを選ぶ過程で、いくつかのポイントが見つかりました。







 def jsonify(*args, **kwargs): ... if args and kwargs: raise TypeError('jsonify() behavior undefined when passed both args and kwargs') elif len(args) == 1: # single args are passed directly to dumps() data = args[0] else: data = args or kwargs
      
      





ここで何かが起こっています。 それは私が理解しているすべてです。







そしてこれ:







 def make_response(*args): if not args: return current_app.response_class() if len(args) == 1: args = args[0] return current_app.make_response(args)
      
      





そして今、ベリー:







 class Flask(_PackageBoundObject): def make_response(self, rv): status_or_headers = headers = None if isinstance(rv, tuple): rv, status_or_headers, headers = rv + (None,) * (3 - len(rv))
      
      





すべて燃えます!







PSなぜ私はあの記事を書いているのですか? その週、たとえば火曜日に(もっと収容するために)バー(サンクトペテルブルク、ズヴェズドナヤ地区)に行きたい人は誰ですか?..受信トレイに書き込みます。







PPS Habr、なぜテキストを印刷しないのですか? ここで、私も物事を書きました!








All Articles