📜 ⬆️ ⬇️

What the flask?

kdpv
Actually, this is a picture from wtforms, but for some reason my gimp doesn't start.


I am writing this article in a bar. I really want to talk a little, but the barman looks at me with round eyes, and the hookah man just smiles and shakes his head.


Once, I was asked: what's wrong with a flask? Then I was completely satisfied with this cute framework. Having worked with him for some time, I wrote everything I think, a worker is weak, to which I was answered: "Murad, be kinder." Actually, I'm kind and fluffy, but wtf ?!


It is worth noting that I am a big fan of the work of Armin . His packages are used in many of my projects. And he is an incredible thorn in the Python community. And this is good.


Flask


Flask is a wrapper over very cool detached projects. Some compare it with janga. I xs why.


If you try to describe all the problems of Flask in two points:


  1. imports
  2. request context

Everything. Then you can not read. But if it is still not clear, look further.


Blueprints


If in janga all applications are connected to INSTALLED_APPS , then the concept of blueprints used in the blueprints . This application and a separate namespace url in one bottle:


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

Further, you can route urls like this: url_for('simple_page.index') .


Nesting


And it is not. You can not just take and make an embedded namespace. You can find “solutions” on the web, but here I’ll only look at boxed flagship, because you can write everything.


Imports


When you do this in the production code:


 if foo == 3: do_stuff(foo) 

Somewhere in the world I'm sad! Take care of me, take it to the settings.


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

Conceptually. But it will not work. Because a couple of lines ago, we imported the package into myapp and forever ordered our way there.


Wait, there must be a way out! Aha


 from flask import current_app 

And it does not work. Because current_app is available only in context of the request!


- Finally, bring it to the settings file of the application, you bastard! - voice from the audience.
- And how will I replace them on the prode or test, huh?


By the way, I have a special battery for this case.
Just imagine the wonderful wonderful world where django.conf.settings is available only in the context of a request!


flask.g


It is impossible not to joke about the same point. And most importantly, it does not need to search, it is always here: flask.g . Bad boom shh!
That's why Armin is my idol!


You can send everything you need into it:


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

However, this will work only in the context of a request, like any other magical objects of the fusion.


Routing URLs and their methods


I have such a piece of urls on my site :


 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 processes only one method - POST . Guess what happens if you ask for GET ? Aha, 404. It is provided by the second view.
To get NOT ALLOWED , you need to explicitly return 405 to ApiView !


Fask, what's wrong with you?


Steak!


A. Wait a minute. That's for me. Omnom-omnom.


flask-wtf. CSRF


Oh. Suppose we need to turn off the check in one view:


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

So we need an app . Remember imports, right? We are looking for a way out, we climb in sortsy:


 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 

Hooray! You can pass the path to the view (in the version that came out two weeks ago)! We try:


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

Does not work. Actually (I hate this expression), we changed the name of the view when we called ApiView.as_view('api_view') :


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

And "all the same" that we indicate the path to an object that does not exist. Works! Does not work.


Do you know why? Because the form. She doesn't know anything about the view:


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

Now it works.


url_for ()


Suppose you want to do this:


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

Forget it. Out of context does not work. Probably, you can make your lazy object, in the end, it didn’t immediately appear in janga either.


flask-testing


Stuck, designed to help with the tests. For example, you can look at the context that is passed to the template. And let's try:


 AssertionError: Popped wrong request context. 

Oh. Something went wrong. And you know what? I don't know either.
Actually (I hate this expression), I grabbed NotImplementedError in one of the methods that I did not override. But the point is that dropping the tests, you will never understand the reason.


Any different


In the process of picking up a flake, I found several points:


 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 

Something is happening here. That is all I understand.


And this:


 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) 

And now the berries:


 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)) 

All burn!


PS Why am I writing articles alone, m? Who wants to go to the bar (in St. Petersburg, in the Starry area) on Tuesday (say, to accommodate more) that week? .. Write in inbox.


PPS Habr, why aren't you typing texts? Here, I even wrote a piece !


')

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


All Articles