Flask Web Development Notes
Flask Web Development Notes
这是我暑假看 Miguel 的那本著名狗书时的笔记,书的版本是最新的 second edition。当时看的是原文版,以后会写一篇文章说阅读英语原文的经验
Ch2 Basic Application Structure
Run an app
1 | export FLASK_APP=name.py |
Dynamic route
Flask supports the types string, int, float, and path for routes. The path type is a special string type.
Response
view function could take as much as three arguments, status code and a dictionary of headers
1 |
|
Compatibility with older version
app.run(debug=True)
app.add_url_rule(): builds the map between URL and view function
1 | flask run --host 0.0.0.0 |
1 | git reset --hard |
1 | sudo apt-get install sqlite3 libsqlite3-dev |
Ch3 Templates
business logic and presentation logic, Jinja2 takes the work of presentation. More specifically, the application only sends variables to Jinja2, after that how the HTML page is presented is up to Jinja2.
What this chapter’s mainly about
Static web pages. Topics in this chapter:
- What are templates; how to inherit
- How to write URLs in Flask;
url_for()helper function; relative & absolute URLs, the latter one less useful - How to send static files (in template format)
- Miscellaneous: Bootstrap integration
Ch4 Web Forms
Form classes (technical)
FlaskForm defines the list of fields in each form, each represented by an object. Each field object have one or more validators attached. A validator is a function. Note the three terms here, FlaskForm, field, validator.
Form submission with GET
Bad. GET doesn’t have a body, so if submit with GET method, the data will be appended to the URL as a query string, and becomes visible in the browser’s address bar.
Therefore, in view function that deals with forms, add a POST method like that:
1 |
Miscellaneous
This method returns True when form is submitted submitted using POST method, and the data accepted by all field validators; used to determine, whether the form needs to be rendered or processed.
1 | if form.validate_on_submit(): |
The first and only required argument to url_for() is the endpoint name. By default, the endpoint of a route is the name of the view function attached to it.
1 | return redirect(url_for('index')) |
Ch5 Databases
Terms
column: attribute of the entity; row: actual data element that assigns values to columns.
table, record –> collection, document, from Relational to NoSQL
primary key: a special column; foreign keys: columns
Sum
- With ORM middleman, one doesn’t have to SQL semantics
- Apply different URLs in config could migrate from different (relational) databases
- Databases migration:
- Framework: Flask-Migrate, the Alembic wrapper
- Procedures:
flask db init, creates a migrations directory (optional, only on a new project);flask db migrate -m "message", automatically creates migration script, whilerevisionmanually;flask db upgrade flask db downgradeand... upgradegives db migrations log history like git
Ch7 Large Application Structure
Add custom commands via click
1 |
|
Blueprint detail
In chapter 7 about blueprint, the module where blueprint object is must import its routes’ view functions, because
Importing these modules causes the routes and error handlers to be associated with the blueprint.
From Eg.7.7: the blueprint name before endpoint can be omitted, as
url_for('.index'). Redirects within the same blueprint could use the shorter form, while crossing blueprints requires the fully qualified endpoint name that includes the blueprint name.
Ch8 User Authentication
Hashing functions are repeatable.
- Q: How could the
check_password_hash(hash, password)check pwd without knowing the salt of it?
WTForm: write your own validator with validate_ prefix
- for
wtformsvalidate_ prefix defines custom validators; while in Python standard libraryunittestthe test_ prefix is used. - any function referred the database, is defined in
model.py, as methods in those ORM models. They access the database usingself.attribute.
Flask-Login detail
Flask-Login requires the application to designate a function to be invoked when the extension needs to load a user from the database given its identifier, registered with @login_manager.user_loader decorator.
_get_user() searches for a user ID in the user session –> invoke the function registered with the user_loader decorator, with the ID as argument
Ch14 API
The process of converting an internal representation to a transport format such as JSON is called serialization.
Todo
decorators in Python
They are functions that takes a func as an arg then returns another argOOP concepts: constructor, method&attribute
(so far I assume that) Methods are funcs, attributes are data.How blocks are really defined in bootstrap/base.html
what
<>means in Python code (<{'key1': v, 'k2': v2}>)What is label in HTML
makes the form text clickable; same style with it.The remaining class variables are the attributes of the model, defined as instances of the
db.Columnclass.what is instance, class variable, attribute
withkeyword in Python__name__,__file__and other dunder variable (basedir = os.path.abspath(os.path.dirname(__file__)))__name__has two values,"__main__"(when being executed) or the module’s name (when imported). With respect to Object,__name__is the special attribute of a class, function, method, descriptor, or generator instance.__file__, the absolute path of the module
functionality of the
__init__.pyfile in a directoryOOP:
@propertydecorator in a classDB:
users = db.relationship('User', backref='role', lazy='dynamic'). “users” is a column of the table role. What doeslazykwarg meanDB:
Role.query.filter_by(name='Administrator').first(), type of the return value1
2
3User.query.filter_by(username='galt').first() # output: <User 'john'>
a = User.query.filter_by(username='galt').first()
type(a) # output: <class 'app.models.User'>On success, return value is the row in the table.
a.idwould return theidcolumn of usergalt.
- Linux command
export -
form.hidden_tag()element for CSRF protection - How much freedom does ORM/ODM provide in choosing DB, only different rational databases?
Yes. -
{{ wtf.quick_form(form) }}, how will this template be rendered, search keyword in the book{{ name }}construct references a variable, a placeholder
- How to initialize
SelectField, 7.31 -
Post.query.order_bywill this query affect rows? 8.1
After Flask:
WTForm package validator source code, I assume it’s just RegEx
For example, the execution of the
send_async_email()function can be sent to a Celery task queue. (p.107)Decorator: How different orders affects the registered function
Thread: worker thread in Flask doc
Iterator and that:
1
2follows = [{'user': item.follower, 'timestamp': item.timestamp}
for item in pagination.items]
Check yourself:
- How to add a new row in a table, how to change a column of a row
- Page 182, how the foreign key of a table is added
synopsis: brief summary
delimiter (programming)
miscellaneous
callable, page 65
cardinality alchemy, transparent (Ch5)
build a perfect replica of the virtual environment…
Appendix
Object in Python
type of methods:
- instance method, the 1st argument of it must be
self; any method takingselfas the 1st arg is a instance method - class method,
@classmethod,clsas the 1st arg. Calling:Obj().count(), whereObjis the name of a class - static method,
@staticmethod. E.g.Obj().someStaticMethod()
super() in Python2.x takes its own class as the first variable, like super(Child, self).__init__(age, height). Also the parent shall be defined as class Parent(object), having object as base class.
REST API
- more business logic on client side
- client could discover resources using different URL compositions
- versioning for backward compatibility
Compare to Mage Tutorial
- _get
- plain text and HTML email
- from GitHub’s commit history you could view specifically what changed in every commit
Test & Caution
Think of boundary values while designing programs.
current_user.confirmed@login_requiredself.email.lower()ensure that the string is lowercaseverify_password(email, password):before loading user from DB to check pwd,emailmust be checked first not to be''
Crucial cases where proxies provided by Flask like
current_appcan’t fake:current_appcan’t fake its type as the actual object type- when sending Signals or passing data to a background thread
best practice:
1
2app = current_app._get_current_object()
my_signal.send(app)from sqlalchemy.exc import IntegrityError try: db.session.commit() except IntegrityError: db.session.rollback()form.body.data = post.body; how to render page according to attributes of the user; Context processors make variables available to all templates during renderingfrom app.exceptions import
The power of Flask Shell
Page 214, static method add_self_follows() that manipulates existed rows