Giter VIP home page Giter VIP logo

flask-concepts's Introduction

Flask

Flask

  • All flask applications must create an application instance.
  • The web server passes all the requests from the clients to this object for handling, using a protocol called Web Server Gateway Interface.
  • The application instance is an object of class Flask. It takes the name of the main module or package of the application as the argument.
from flask import Flask
app = Flask(__name__)

Route and View functions

  • The association between a URL and the function that handles it is called a route.
@app.route('/')
def index():
    return '<h1>Hello, World!</h1>'
  • The return value of the function is called the response.
  • The function index() is called a view function.
  • Dynamic component in flask
@app.route('user/<name>')
def user(name):
    return '<h1>Hello, %s!</h1>' % name
  • Dynamic component in routes are strings by default but can also be defined with a type. Example: ‘/user/int:id’ - would match only URLs that have an integer in the id dynamic segment.
  • Flask supports int, float, and path for routes. The path type alse represents a string but does not consider slashes as separators and instead considers them part of the dynamic component.

The Request-Response Cycle

  • When Flask receives a request from a client, it needs to make a few objects available to the view function that will handle it. A good example is a request object.
  • The obvious way in which Flask could give a view function access to the request object is by sending it as an argument, but that would require every single view function in the application to have an extra argument. Things get more complicated if you consider that the request object is not the only object that the view functions might need to access to fulfill a request.
  • Flask uses contexts to temporarity make certain objects globally accessible to avoid cluttering view functions with a bunch of arguments.
from flask import Flask, request

app = Flask(__name__)

@app.route('/')
def index():
	return '<p>%s</p>' %request.headers

if __name__ == '__main__':
	app.run(debug=True)
  • Note how in the above view function request is used as if it was a global variable.
  • In reality, request cannot be global variable if you consider that in a multithreaded server the threads are working on different requests from different clients at the same time, so each thread need to see a different object in request.
  • Contexts enables Flask to make certain variables gloablly accessible to a thread without interfering with the other threads.
  • A thread is the smallest sequence of instructions that can be managed independently. It is common for a process to have multiple active threads, sometimes sharing resources such as memory or file handles. Mutlithreaded web servers start a pool of threads and select a thread from the pool to handle each incoming request.
  • There are two types of context in Flask: application context and the request context.
Variable NameContextDescription
current appApp ConThe application instance for the active application
gApp ConAn object used as temp storage for each request
requestReq ConContents of a HTTP request sent by the client as obj
sessionReq ConDict, used to store values used between requests

Request Dispatching

  • When the application receives a request from the client, it needs to know which view function to be invoked.
  • Flask looks up the URL given in the request in the application’s URL map, which contains a mapping of URLs to the view function that handle them.
>>> app.url_map
Map([<Rule '/static/<filename>' (GET, HEAD, OPTIONS) -> static>,
 <Rule '/' (GET, HEAD, OPTIONS) -> index>,
 <Rule '/user/<name>' (GET, HEAD, OPTIONS) -> user>,
 <Rule '/user/<userId>' (GET, HEAD, OPTIONS) -> userId>])
  • Head, Options and Get are the request methods that are handled by the route.

Request Hooks

  • Sometimes it is useful to execute code before or after each request is processed, eg: connection to database.
  • Instead of duplicating the code in every view function, flask offers an option to register common functions to be invoke before or after a request is dispatched to a view function.
  • Request hooks are implements as decorators.
Request HooksUsed
before first requestRegister a function to run before the first req is handled
before requestRegister a function to run before each request
after requestRegister a function to run after each request, if no unhandled exceptions occurred
teardown requestRegister a function to run after each request, even if unhandled exceptions occurred

Responses

  • When Flask invokes a view function, it expects its return values to be the response of the request. In most cases, its just a string.
  • The HTTP protocol requires more than a string as a response to the request such as a status code.
  • By default, 200 is the sent by Flask. To add something else pass it as a second return value after the response text.
@app.route('/')
def index():
    return '<h1>Bad request</h1>', 400
  • It can also take a third argument, a dictionary of headers that are added to the HTTP response.
  • Instead of returning one, two, or three values as a tupe, Flask view functions have the option of returning a Response object.
  • The make response() function takes one, two, or three arguments and returns as a Response object.
from flask import make_response

@app.route('/')
def index():
    response = make_response('<h1>This document carries a cookie!</h1>')
    response.set_cookie('answer', '42')
    return response
  • There is another special type of response called a redirect for redirecting.
@app.route('/')
def index():
    return redirect('https://thekafkaa.online')

Templates

  • A template is a file that contains the text of a response, with placeholder variables for the dynamic parts that will be known only in the context of a request. The process that replaces the variables with actual vaues and returns a final response string is called rendering.
  • Flask used Jinja2 for rendering.
from flask import Flask, render_template
app = Flask(__name__)

@app.route('/')
def index():
    return render_template('index.html') // templates/index.html

@add.route('/user/<name>')
def user(name):
    return render_templete('user.html', name = name)
  • Jinja2 recognizes variables of any type, even comples types such as lists, dictionaries and objects.
<p>A value from a dictionary: {{ mydict['key'] }}.</p>
<p>A value from a list: {{ mylist[3] }}.</p>
<p>A value from a list with a variable index: {{ mylist[myintvar] }}.</p>
<p>A value from an object's method: {{ myobj.somemethod() }}.</p>
  • Variable can be modified with filters which are added after the variable name with a pipe as separator.
<p>Hello, {{ name|capitalize }}.</p>
  • Jinja also offers control stuructures. Following is how conditionals are done.
{% if user %}
    Hello, {{ user }}!
{% else %}
    Hello, Stranger!
{% endif %}
  • Following is a demonstrations of a for loop
 <ul>
   {% for comment in comments %}
	<li>{{ comment }}</li>
   {% endfor %}
 </ul>
  • Jinja also supports macros, which are similar to python code.
 {% macros render_comment(comment) %}
     <li>{{ comment }}</li>
 {% endmacros %}

 <ul>
   {% for comment in comments %}
	{{ render_comment(comment) }}
   {% endfor %}
 </ul>  
  • To make macros more reusable, they can be stored in a standalone files that are then imported from all the templates that need them.
 {% import 'macros.html' as macros %}

 <ul>
   {% for comment in comments %}
	{{ macros.render_comment(comment) }}
   {% endfor %}
 </ul>
  • Portions of template code that need to be repeated in several places can be stored in a separate file and included from all the templates to avoid repitition.
{% include 'common.html' %}
  • Jinja also provides template inheritance for powerful reuse, first a base template is created with the name base.html.
<html>
  <head>
    {% block head %}
    <title>{% block title %}{% endblock %} - My application</title>
    {% endblock %}
  </head>
  <body>
    {% block body %}
    {% endblock %}
  </body>
</html>
{% extends "base.html" %}
{% block title %}Index{% endblock %}
{% block head %}
    {{ super() }}
{% endblock %}
{% blockbody %}
<h1>Hello, World!</h1>
{% endblock %}

Links

  • Any application that has more than one route will invariably need to include links that connect the differnet pages, such as in a navigation bar.
  • Writing the URLs as links directly in the template is trivial for simple routes, but for dynamic routes with variable portions it can get more complicated to build the URLs right in the template.
  • To avoid these problem, Flask provies the urlfor() helper function, which generates URLs from the informatioon stored in the application’s URL map.
@app.route('/user/<name>')
def user():
    print(url_for('user', name=name)
  • Using static file for a file url.
{% block head %}
{{ super() }}
<link rel="shortcut icon" href="{{ url_for('static', filename = 'favicon.ico') }}"
 type="image/x-icon">
<link rel="icon" href="{{ url_for('static', filename = 'favicon.ico') }}"
 type="image/x-icon">
{% endblock %}

Web Forms

  • Though forms in Flask can be handled with the help of request object, it becomes tedious and repetitive to generate HTML code for forms and the validations of the submitted form data. Hence Flask-WTF extension is used.
  • Cross Site Request Forgery attack occurs when a malicious website sends requests to a different website on which the victim is logged in. By default, Flask WTF protects forms agains CSRF.
  • To implement CSRF, WTF needs the application to configure an encrytion key. Flask then uses this key to generate encrypted tokens that are used to verify the authenticity of requests with form data.
app = Flask(__name__)
app.config['SECRET_KEY'] = 'hard to guess string'
  • app.config dictionary is a general purpose place to store configuration variables used by the framework, extensions or the applicaiton itself.
  • When using Flask-WTF, each form is representd by a class that inherits from class Form.
from flask_wtf import Form
from wtforms import StringField, SubmitField
from wtforms.validators import Required

class GetNameForm(Form):
    name = StringField('What is your name?', validators=[Required()])
    submit = SubmitField('Submit')

flask-concepts's People

Contributors

mklno avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.