Flask 開發中的踩坑

flask中常用的包有:

  1. Flask
  2. Flask-Cache
  3. Flask-DebugToolbar
  4. Flask-Exceptional
  5. Flask-Login
  6. Flask-Mail
  7. Flask-RESTful
  8. Flask-Script
  9. Flask-SqlAlchemy
  10. Flask-Uploads
  11. Flask-WTF
  12. bcrypt
  13. gunicorn
  14. pymysql
  15. WTForms

1. Flask 目錄結構的選擇

按功能分層次

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

各自優點:

  1. 按功能分層次的優點是各種功能聯系緊密, 公用的代碼易于管理。 適合中小型的項目。 比如blog, cms, 簡易的網上商城。
  2. 按模塊分層次的優點是將各個功能分離出來, 適合模塊化的遷移和公用。 適合稍大的項目, 模塊間聯系不是很緊密的情況。

各自的缺點:

  1. 功能分層的話, 代碼后期的遷移難度增加, 代碼間的公用性太強, 容易牽一發而動全身。 而且當代碼量增加之后, 維護性較差。
  2. 模塊分層的話, 代碼的冗余太多, 許多可以公用的地方無法很好處理, 構造繁瑣, 工期較長。

flask結構常見文件的作用

  1. config.py 主要存放配置信息。 比如DEBUG, mysql, sercertkey等。 可以通過flask的 app.config.from_object('config') 自動導入。
  2. instance/config.py 主要是私人的信息, 可以通過 flask 提供的 app.config.from_pyfile('config.py') 覆蓋前者的配置。
  3. requirements 存放所需要引入的包。
  4. run.py 運行文件, 加入一些運行配置, 比如使用gunicorn配置, 也可以通過添加manager.py文件管理。
  5. views 文件存放路由信息, 俗稱藍圖。 類似于MVC架構中的controllers。
  6. models 數據存放與處理的信息。 類似MVC中的Models。
  7. forms 表單存放的位置。
  8. static 靜態文件的存放。 images/js/css
  9. templates jinja模板文件。
  10. utils 一些常用的方法集合。

2. 使用nginx反向代理時候的域名前綴的坑

如果想要設置網站的訪問為 api.example.com, admin.example.com, example.com。 最簡單的方式就是用nginx來做反向代理。
example.com主要就是傳輸靜態的文件的地址。 主要是主頁面和css, js。 可以直接使用nginx獲取靜態資源, 效率十分高。
api.exmaple.com 和 admin.example.com 則需要代理指向python去執行。 坑出現了。

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做一些配置上的調整。

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 傳遞過去。
此時也必須設置flask的SERVER_NAME參數, 即config.py文件里面的SERVER_NAME = 'fos.dev'.
這樣就可以大功告成了。

3. mysql包的選擇

Flask-SQLAlchemy包默認使用的是MYSQL-python包.
顯然這個包已經兩年多沒有更新了, 所以已經是一個死包了, 而且只支持到2.7版本。
現在還有一個包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 關聯表的設置問題。

關聯表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, 這樣使用的時候,必須確保改對象也在當前文件中, 如果是不同的文件,就需要將另一個文件導入。
因此, 在最外層的init.py中統一導入了所有的對象。

5. flask-script包主要用于自定義一些命令行command.

簡單的命令行很好寫, 值得說的是帶參數的命令行.
第一種是可選單參數(-f, -v, -h)之類的

@manager.command
def db_create(force=False):
    pass

這段代碼中的force參數就是如此, 可以通過 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

這段代碼則是配置多參數的例子, -u/--name 后面輸入的均作為name參數, 比如

python manage.py create_user -u admin

或者

python manage.py create_user --name admin

6. wtforms

如果是一個select 表單, 內容是 sqlalchemy 的對象

# productForm中的category設置方法
category_id = SelectField('category',
    choices=[(str(c.id), c.name) for c in Category.query.order_by('name')],
    validators=[
        DataRequired()
    ])

尤其注意的是, choices的value值必須設置為str類型, 因為form表單傳送過來的是string, python是強類型的語言,所以用string對應。

fieldList的使用

# product_image中的設置
class MultiProductImageForm(BaseForm):
    images = FieldList(FileField('Image File',
        validators=[
            DataRequired(),
            ImageFileRequired()
        ]), min_entries=1)

min_entries這個參數必須是kw, 而且只能在初始時期綁定, 后期調用init方法綁定的話, 參數傳遞會有問題, 有機會重寫一下, 或者重寫它的 new方法。
總體來說這個包不夠自動化,需要填的坑很多,慎用。

有關的實踐代碼在點此 github

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,663評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,125評論 3 414
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 175,506評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,614評論 1 307
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,402評論 6 404
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,934評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,021評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,168評論 0 287
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,690評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,596評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,784評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,288評論 5 357
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,027評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,404評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,662評論 1 280
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,398評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,743評論 2 370

推薦閱讀更多精彩內容

  • 22年12月更新:個人網站關停,如果仍舊對舊教程有興趣參考 Github 的markdown內容[https://...
    tangyefei閱讀 35,199評論 22 257
  • Spring Cloud為開發人員提供了快速構建分布式系統中一些常見模式的工具(例如配置管理,服務發現,斷路器,智...
    卡卡羅2017閱讀 134,776評論 18 139
  • 學習 Flask,寫完一個 Flask 應用需要部署的時候,就想著折騰自己的服務器。根據搜索的教程照做,對于原理一...
    Cocoa_Coder閱讀 17,186評論 4 56
  • flask是python的一個web應用框架,django很多人聽過,flask比較少見,連創始人一開始寫出來只是...
    思而憂閱讀 2,951評論 0 5
  • [TOC]一直想做源碼閱讀這件事,總感覺難度太高時間太少,可望不可見。最近正好時間充裕,決定試試做一下,并記錄一下...
    何柯君閱讀 7,200評論 3 98