「Flask」02: Static File handling, Database connection
前陣子用 Flask 實做了一個 LifePlaylist App 這裡簡單紀錄一下基本的東西,以後回頭更快重拾記憶🤧 - 第二篇
"A lightweight Python Web Framework ! " ---->
Flask Docs
Path: /static/images/01.jpg
1
2
3
4
|
## HTML:
<img src="/static/images/01.jpg">
## Browser:
<img src="/static/images/01.jpg">
|
Path: /views/assets/01.jpg
1
2
3
4
5
6
7
8
9
10
11
12
13
|
app = Flask(__name__, static_folder="views/assets/")
app = Flask(__name__, static_folder="images/")
## or
app = Flask(__name__, static_folder="./views/assets/")
app = Flask(__name__, static_folder="./images/")
## HTML:
<img src="{{ url_for('static', filename='01.jpg') }}">
# <img src="01.jpg">
## Browser:
<img src="/assets/01.jpg">
<img src="/images/01.jpg">
|
1
2
3
4
5
6
|
app = Flask(__name__, static_url_path="/Hello", static_folder="views/assets/")
## HTML:
<img src="{{ url_for('static', filename='01.jpg') }}">
# <img src="/Hello/01.jpg">
## Browser:
<img src="/Hello/01.jpg">
|
But actually image is still under the path views/assets/
- Also support SQLAlchemy
- Raw SQL / ORM
Flask-SQLAlchemy: Docs
SQLAlchemy: Docs
pip install flask-sqlalchemy
from flask_sqlalchemy import SQLAlchemy
app.config['SQLALCHEMY_DATABASE_URI'] = [DB_TYPE]+[DB_CONNECTOR]://[USERNAME]:[PASSWORD]@[HOST]:[PORT]/[DB_NAME]
1
2
3
4
5
6
7
8
9
10
11
|
app.config['SQLALCHEMY_DATABASE_URI'] = "sqlite:////db/testing.db" ("sqlite:///" + absolute path + name.db)
## folder: /db/
## db name: testing.db
## 'sqlite:////absolute/path/to/foo.db'
## -----------
import os
basedir = os.path.abspath(os.path.dirname(__file__))
def create_sqlite_uri(db_name):
return "sqlite:///" + os.path.join(basedir, db_name)
|
pip install pymysql
1
2
3
4
5
|
app.config['SQLALCHEMY_DATABASE_URI'] =
mysql+pymysql://[user_name]:[user_password]@[HOST]:3306/[db_name]
## e.g.
mysql+pymysql://root:password@localhost:3306/myapp
|
pip install psycopg2-binary
1
2
3
4
5
6
7
8
|
app.config['SQLALCHEMY_DATABASE_URI'] =
postgresql://[user_name]:[user_password]@[HOST]:5432/[db_name]
## e.g.
## no password
postgresql://linpinhung:linpinhung@localhost:5432/app_pro
## HOST should be different depend on where your db is, for example, I set it in Docker, then my HOST will depend on what I configure.
postgresql://name:name@db:5432/app_docker
|
app.config['SQLALCHEMY_ENGINE_OPTIONS'] = {
'pool_pre_ping': True,
'pool_recycle': 300,
'pool_timeout': 900,
'pool_size': 10,
'max_overflow': 5,
.....: ...,
....
....
}
- SQLALCHEMY_ECHO(For debug):
- Default: False
- If True, print Raw SQL in console
- SQLALCHEMY_RECORD_QUERIES
- If True, can check query detail
from flask_sqlalchemy import get_debug_queries
def after_request(response):
for query in get_debug_queries():
print(query.statement)
print(query.parameters)
print(query.duration)
print(query.context)
return reponse
get_debug_queries can also use in other ways.
model/models.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
from flask_login import UserMixin
from sqlalchemy.sql import func
from app import db
class Playlist(db.Model):
id = db.Column(db.Integer, primary_key=True)
artist = db.Column(db.String(500))
artist_spotify_uri = db.Column(db.String(500))
artist_spotify_image_url = db.Column(db.String(500))
song = db.Column(db.String(500))
artist_genres = db.Column(db.JSON)
date = db.Column(db.DateTime(timezone=True), default=func.now()) # 拿到當下時間
user_id = db.Column(db.Integer, db.ForeignKey('user.id')) # 拿使用者 id 當 fk
# user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False) # 拿使用者 id 當 fk
test_migrate_col = db.Column(
db.String(120), nullable=True) # 預設就是 nullable=True 可以不寫
def __init__(self, artist, song, user_id):
self.artist = artist
self.song = song
self.user_id = user_id
class User(db.Model, UserMixin):
id = db.Column(db.Integer, primary_key=True)
email = db.Column(db.String(150), unique=True)
password = db.Column(db.String(150))
first_name = db.Column(db.String(150))
playlists = db.relationship('Playlist')
# playlists = db.relationship('Playlist', backref='user')
def __init__(self, email, password, first_name):
self.email = email
self.password = password
self.first_name = first_name
|
self.model.query.get(id)
Playlist.query.get(id)
self.model.query.all()
Playlist.query.all()
1
2
3
4
5
6
7
8
9
|
## method 1
self.model.query.filter_by(**filter_dic).all()
## method 2
my_filters = {'artist':'xxxxx', 'song':'xxxxx'}
query = session.query(self.model)
for attr,value in my_filters.iteritems():
query = query.filter( getattr(self.model,attr)==value )
results = query.all()
|
row = self.get_data(id)
db.session.delete(row)
db.session.commit()
1
2
3
4
5
6
7
8
9
10
11
12
13
|
new_top10_data = Dashboard(
dashboard_artist=i.artist, dashboard_song=i.song, artist_spotify_uri=i.spotify_uri, artist_spotify_image_url=i.spotify_image_url, song_youtube_url=i.youtube_url, artist_genres=i.genres)
db.session.add(new_top10_data)
db.session.commit()
## -----------------
## Usage:
## Dic: **Dic
## List: *List
def insert_data(self, insert_dic):
new_data = self.model(**insert_dic)
db.session.add(new_data)
db.session.commit()
|
- Static File handling try to use
url_for
will be better.
static_url_path
can hide the real path.
- DB connection should careful for the
path
/ host, user, password
/ dependencies
「Flask」01: Basic, Route, Templates, GET, POST