flask中常用的包有:
- Flask
- Flask-Cache
- Flask-DebugToolbar
- Flask-Exceptional
- Flask-Login
- Flask-Mail
- Flask-RESTful
- Flask-Script
- Flask-SqlAlchemy
- Flask-Uploads
- Flask-WTF
- bcrypt
- gunicorn
- pymysql
- WTForms
1. Flask 目錄結(jié)構(gòu)的選擇
按功能分層次
test-demo
├── config.py
├── instance
│ └── config.py
├── requirements.txt
├── run.py
└── test_demo
├── forms
│ └── __init__.py
├── __init__.py
├── models
│ ├── __init__.py
│ └── User.py
├── static
│ └── style.css
├── templates
│ ├── admin
│ │ └── base.html
│ ├── api
│ │ └── base.html
│ └── base.html
├── utils
│ └── __init__.py
└── views
├── admin
│ ├── __init__.py
├── api
│ ├── __init__.py
└── __init__.py
按模塊分層次
.
├── config.py
├── instance
│ └── config.py
├── requirements.txt
├── run.py
└── test_demo
├── admin
│ ├── forms
│ │ └── __init__.py
│ ├── models
│ │ ├── __init__.py
│ │ └── User.py
│ ├── templates
│ │ └── base.html
│ ├── utils
│ │ └── __init__.py
│ └── views
│ └── __init__.py
├── api
│ ├── forms
│ │ └── __init__.py
│ ├── models
│ │ ├── __init__.py
│ │ └── User.py
│ ├── static
│ │ └── style.css
│ ├── templates
│ │ └── base.html
│ ├── utils
│ │ └── __init__.py
│ └── views
│ └── __init__.py
└── __init__.py
各自優(yōu)點:
- 按功能分層次的優(yōu)點是各種功能聯(lián)系緊密, 公用的代碼易于管理。 適合中小型的項目。 比如blog, cms, 簡易的網(wǎng)上商城。
- 按模塊分層次的優(yōu)點是將各個功能分離出來, 適合模塊化的遷移和公用。 適合稍大的項目, 模塊間聯(lián)系不是很緊密的情況。
各自的缺點:
- 功能分層的話, 代碼后期的遷移難度增加, 代碼間的公用性太強, 容易牽一發(fā)而動全身。 而且當(dāng)代碼量增加之后, 維護(hù)性較差。
- 模塊分層的話, 代碼的冗余太多, 許多可以公用的地方無法很好處理, 構(gòu)造繁瑣, 工期較長。
flask結(jié)構(gòu)常見文件的作用
- config.py 主要存放配置信息。 比如DEBUG, mysql, sercertkey等。 可以通過flask的 app.config.from_object('config') 自動導(dǎo)入。
- instance/config.py 主要是私人的信息, 可以通過 flask 提供的 app.config.from_pyfile('config.py') 覆蓋前者的配置。
- requirements 存放所需要引入的包。
- run.py 運行文件, 加入一些運行配置, 比如使用gunicorn配置, 也可以通過添加manager.py文件管理。
- views 文件存放路由信息, 俗稱藍(lán)圖。 類似于MVC架構(gòu)中的controllers。
- models 數(shù)據(jù)存放與處理的信息。 類似MVC中的Models。
- forms 表單存放的位置。
- static 靜態(tài)文件的存放。 images/js/css
- templates jinja模板文件。
- utils 一些常用的方法集合。
2. 使用nginx反向代理時候的域名前綴的坑
如果想要設(shè)置網(wǎng)站的訪問為 api.example.com, admin.example.com, example.com。 最簡單的方式就是用nginx來做反向代理。
example.com主要就是傳輸靜態(tài)的文件的地址。 主要是主頁面和css, js。 可以直接使用nginx獲取靜態(tài)資源, 效率十分高。
api.exmaple.com 和 admin.example.com 則需要代理指向python去執(zhí)行。 坑出現(xiàn)了。
server {
listen 80;
server_name api.fos.dev;
server_name admin.fos.dev;
location / {
proxy_pass http://127.0.0.1:5000;
proxy_read_timeout 86400s;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
本來是這樣配置的nginx, 這時候, flask獲取到的server_name 其實是 127.0.0.1:5000這個東西, 但是這個東西無法添加subdomain. 也就是無法這樣顯示:
api.127.0.0.1:9000, admin.127.0.0.1:9000
因此這兒需要對nginx做一些配置上的調(diào)整。
server {
listen 80;
server_name api.fos.dev;
server_name admin.fos.dev;
location / {
proxy_pass http://127.0.0.1:5000;
proxy_read_timeout 86400s;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
添加了
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $remote_addr;
將nginx接受到的 server_name 傳遞過去。
此時也必須設(shè)置flask的SERVER_NAME參數(shù), 即config.py文件里面的SERVER_NAME = 'fos.dev'.
這樣就可以大功告成了。
3. mysql包的選擇
Flask-SQLAlchemy包默認(rèn)使用的是MYSQL-python包.
顯然這個包已經(jīng)兩年多沒有更新了, 所以已經(jīng)是一個死包了, 而且只支持到2.7版本。
現(xiàn)在還有一個包pymysql, 這才是未來啊。
使用pymysql包只需將config.py里面的:
SQLALCHEMY_DATABASE_URI = 'mysql://username:password@server/fos'
改為
SQLALCHEMY_DATABASE_URI = 'mysql+pymysql://username:password@server/fos'
這個包支持 2 ~ 3.5.
4. relations 關(guān)聯(lián)表的設(shè)置問題。
關(guān)聯(lián)表ontToMany之間使用的是
#products.py表 一對多
product_images = db.relationship('ProductImage', back_populates='product', lazy='dynamic')
#product_image表 多對一
product_id = db.Column(db.Integer, db.ForeignKey('products.id'))
product = db.relationship("Product", back_populates="product_images")
使用的是 對象的名字來代表該表。 如ProductImage, Product, 這樣使用的時候,必須確保改對象也在當(dāng)前文件中, 如果是不同的文件,就需要將另一個文件導(dǎo)入。
因此, 在最外層的init.py中統(tǒng)一導(dǎo)入了所有的對象。
5. flask-script包主要用于自定義一些命令行command.
簡單的命令行很好寫, 值得說的是帶參數(shù)的命令行.
第一種是可選單參數(shù)(-f, -v, -h)之類的
@manager.command
def db_create(force=False):
pass
這段代碼中的force參數(shù)就是如此, 可以通過 db_create 之后加上 -f/--force賦值True, 否則其他的均為False, 包括直接 python manage.py db_create force
@manager.option('-u', '--name', dest='name', default='admin')
@manager.option('-p', '--password', dest='password', default='123456')
def create_user(name, password):
pass
這段代碼則是配置多參數(shù)的例子, -u/--name 后面輸入的均作為name參數(shù), 比如
python manage.py create_user -u admin
或者
python manage.py create_user --name admin
6. wtforms
如果是一個select 表單, 內(nèi)容是 sqlalchemy 的對象
# productForm中的category設(shè)置方法
category_id = SelectField('category',
choices=[(str(c.id), c.name) for c in Category.query.order_by('name')],
validators=[
DataRequired()
])
尤其注意的是, choices的value值必須設(shè)置為str類型, 因為form表單傳送過來的是string, python是強類型的語言,所以用string對應(yīng)。
fieldList的使用
# product_image中的設(shè)置
class MultiProductImageForm(BaseForm):
images = FieldList(FileField('Image File',
validators=[
DataRequired(),
ImageFileRequired()
]), min_entries=1)
min_entries這個參數(shù)必須是kw, 而且只能在初始時期綁定, 后期調(diào)用init方法綁定的話, 參數(shù)傳遞會有問題, 有機會重寫一下, 或者重寫它的 new方法。
總體來說這個包不夠自動化,需要填的坑很多,慎用。