Flask項目整體思路
結構篇
一、Git使用
1.創建項目代碼倉庫
2.使用Pycharm的VCS-Git-clone項目下載到本地
或者創建本地倉庫 VCS - Import into Version Control - Create Git Repository
3.配置作者信息(命令)
git config user.name moneky
git config user.email [email protected]
讓git管理文件 VCS- git - add
生成版本 文件右鍵 - git - commit - file
4.版本操作
版本對比、撤銷修改、切換版本mixed(代碼不變只切換倉庫)與hard選項(代碼和倉庫的版本都切換)
切換到指定版本號VCS-Git-Reset Head-輸入版本號
5.設置忽略文件
.gitignore : 忽略文件, 如果 不希望git監視項目中的某些文件/文件夾 , 可以將其路徑設置到忽略
6.遠程倉庫
平臺:GitHub、碼雲
pycharm插件安裝gitee
遠程操作: remotes(本地倉庫關聯遠程倉庫)、push(將本地倉庫的版本推送到遠程倉庫)
clone(第一次從遠程倉庫中下載代碼)、 pull(拉取遠程倉庫的版本)
fetch(查詢遠程倉庫的版本)、rebase(合併,遠程版本的變化會直接合併到當前版本中)
merge(遠程版本和本地版本的變化會合併到一個新的版本中)
7.避免代碼衝突
儘量不要修改同一個文件
不要擅自修改別人的代碼
多進行推送和拉取的操作
8.多人協同-創建分支
作用:隔離開發主線,當開發新功能時,一般會開闢新的開發分支,在開發分支中進行開發,開發成功後,將開發分支中的版本合併回主分支。
新分支相當於對倉庫進行的一個完整的拷貝。
9.打標籤
作用:給重要的版本進行標記,方便快速切換到目標版本
項目經理:創建標籤、推送到遠程倉庫
開發人員:拉取遠程的標籤、切換到標籤對應的版本,進行一些開發
二、項目的基本配置流程
1.項目初始化-導入flask,構建基本結構,設置調試模式
2.導入SQLAlchemy,創建mysql數據庫連接
3.導入Redis,創建Redis數據庫連接
4.導入Session,配置網站session機制,一般用redis儲存
5.將配置信息封裝到Config類中,方便統一管理信息
6.創建管理器,創建管理器後需要腳本啓動runserver
from datetime import timedelta
from flask import Flask, session
from flask_sqlalchemy import SQLAlchemy
from redis import Redis
from flask_session import Session
from flask_script import Manager
app = Flask(__name__)
class Config: # 方便統一管理配置信息
DEBUG = True # 設置調試模式
SQLALCHEMY_DATABASE_URI = "mysql://root:[email protected]:3306/info24" # 設置mysql連接地址
SQLALCHEMY_TRACK_MODIFICATIONS = False # 設置是否追蹤數據庫變化
REDIS_HOST = "127.0.0.1" # 自定義配置信息 設置redis綁定的ip
REDIS_PORT = 6379 # 設置redis監聽的端口
SESSION_TYPE = "redis" # 設置redis的存儲類型
SESSION_REDIS = Redis(host=REDIS_HOST, port=REDIS_PORT) # 設置redis連接對象, 組件內部會使用該對象進行數據的存取
SESSION_USE_SIGNER = True # 設置sessionid是否加密
SECRET_KEY = "TGe7rhO8VaN4r/EDcRHqcr2/wO9G1wiJVWcAj3tSfyXnunbkp0kXbFW22WzIoZPn" # 設置應用祕鑰, 用於sessionid加密
PERMANENT_SESSION_LIFETIME = timedelta(days=7) # 設置session的過期時間, 默認是支持設置過期時間的
# 從對象中加載配置
app.config.from_object(Config)
# 創建mysql連接
db = SQLAlchemy(app)
# 創建redis連接
rs = Redis(host=Config.REDIS_HOST, port=Config.REDIS_PORT)
# 初始化session存儲組件
Session(app)
# 創建管理器
mgr = Manager(app)
@app.route('/')
def index():
# session的存取和之前的使用方式一樣
session["name"] = "zs"
return "index"
if __name__ == '__main__':
mgr.run()
三、項目模塊化
開發中有很多代碼環境,不同的代碼環境需要不同的配置信息
需要在Config配置下重寫,定義配置子類
1.開發環境、項目開發階段使用的配置環境,一般要求開啓試調模式,並記錄所有運行記錄等等
2.生產環境、項目部署上線後使用的配置環境,一般不開啓試調模式,只記錄網站運行的錯誤信息。
四、封裝應用工廠函數
將應用的創建和組件初始化 封裝到應用包中
應用定義工廠函數來封裝處理
config模塊定義配置字典,記錄配置類型和子類的關係
五、封裝視圖函數
將視圖函數封裝到模塊包中、使用藍圖來分管功能模塊
1.在模塊目錄下init文件中創建藍圖對象並讓視圖函數和程序建立關聯
2.在主目錄info文件夾下注冊藍圖對象,並導入藍圖對象
3.在模塊目錄下創建views.py,使用藍圖對象定義路由
六、數據庫對象全局化
1.在工廠函數create_app外將數據庫連接對象,初始化賦值爲None,定義爲全局變量,方便視圖函數進行數據庫操作
2.在工廠函數create_app內聲明全局變量db、rs
七、構建表結構
1.使用數據遷移來生成表結構
在工廠函數中初始化遷移器、關聯模型文件models.py
main.py中生成遷移命令
2.需要讓模型文件和主程序建立關聯
3.遷移數據
python main.py mc init 生成遷移文件夾
python main.py mc migrate -m “註釋” 生成遷移版本
python main.py mc upgrade 執行升級操作
使用cource命令導入sql測試數據文件進入數據庫
八、集成日誌
作用:記錄web應用運行狀態
import logging 導入python提供的內置模塊實現日誌功能,既可以打印在控制檯上也可以寫入到文件中
flask中的默認日誌也是使用的logging模塊,但是flask的默認日誌和自定義日誌都沒有保存到文件中
1.需要我們手動創建日誌文件夾
2.需要忽略日誌文件夾中的日誌文件(文件夾要保留,否則同事沒有日誌文件夾)logs/log*
3.git不會上傳空文件夾,可以添加.keepgit文件來進行文件佔位
4.根據不同的代碼環境使用不同的日誌級別
5.建議使用flask封裝的日誌current_app.logger.error(“出現了錯誤”)
九、路由基本實現
新聞網站需要SEO,路由實現時 優先考慮 後端渲染
拷入靜態文件、導入render_template進行渲染
十、favicon設置
網站的小圖標對應一個固定的URL,該圖標請求是瀏覽器發起的,而且只請求一次
web應用只要實現對應的路由,並且返回圖標圖片即可
flask中提供了一個方法send_static_file,會讀取文件的內容,包裝爲響應對象,並且根據內容自動設置content_type 該方法路徑基於static目錄下
重點代碼:
return cuurrent_app.send_static_file("./imgs/favicon.ico")
十一、項目開發大致流程
1.產品經理會牽頭開產品研討會,展示產品功能,產品需求(產品說明文檔,產品交互文檔)
2.開發人員進行需求分析(項目經理,前後端開發)
3.設計數據庫、構建表結構
4.設計接口文檔(和前端協商接口,一般由後端來完成)
5.根據接口文檔,前後端進行 同步開發(後端實現視圖函數,前端實現頁面)
6.開發完接口用postman進行測試
7.如果是後端渲染 ,可能還要進行前後端聯調
代碼實現篇
一、圖片驗證碼功能
設計接口文檔:
獲取圖片驗證碼:/passport/get_img_code
請求方式 :GET
請求參數:img_code_id 圖片key
響應形式:圖片文件
生成圖片驗證碼 需要安裝第三方包 pip install pillow
代碼思路:
1.在info目錄下創建libs目錄,並把captcha工具包複製進來
2.定義路由,默認get請求
3.用request.args.get(“img_code_id”)獲取參數
4.得到參數進行校驗是否爲空,如果爲空拋出403異常
5.生成圖片驗證碼captcha.generate_captcha( )
6.保存驗證碼文字和圖片key 選擇redis儲存 優勢:快/過期時間/滿足鍵值結構(需要對數據庫做異常處理)
7.返回驗證碼圖片 需要自定義響應對象 設置content-type
二、獲取短信驗證碼
設計接口文檔:
獲取圖片驗證碼:/passport/get_sms_code
請求方式 :POST json
請求參數:
img_code_id 圖片key
img_code 驗證碼文字
mobile 手機號
響應形式:json
需要配合第三方短信集成容聯運
代碼思路:
1.因爲需要獲取手機號和驗證碼,所以需要post請求
2.校驗所有數據是否存在
3.正則匹配手機號格式是否正確
4.根據圖片key取出redis數據庫中的驗證碼文字
5.對比用戶輸入的驗證碼和redis數據庫中的驗證碼是否一致
6.生成隨機驗證碼(這一步也可以將生成的驗證碼打印,方便調試時查看)
7.發送短信之前 判斷用戶是否存在
8調用API發送短信(配合容聯雲通訊API使用)需要配置sms.py文件中的相關API密鑰
9.將生成的驗證碼保存到redis數據庫,設置過期時間
10.返回json形式的發送結果
三、用戶註冊
設計接口文檔:
獲取圖片驗證碼:/passport/register
請求方式 :POST json
請求參數:
sms_code 驗證碼文字
mobile 手機號
password密碼
響應形式:json
代碼思路:
1.因爲要獲取手機驗證碼、密碼、手機號所以用POST請求
2.校驗請求的參數是否爲空,爲空則報錯
3.正則匹配手機號格式是否正確
4.將redis數據庫中的短信驗證碼信息和用戶輸入的進行對比校驗,如果不等的話,提示短信驗證碼錯誤。
5.將用戶手機號,密碼(進行加密),暱稱儲存到mysql數據庫,提交
細節:
使用 計算型屬性 @property 封裝加密過程
使用@password.setter封裝加密操作generate_password_hash(value)
使用session 記錄用戶登錄信息 只需要記錄用戶的主鍵就可以查詢到其他數據
四、用戶登錄
設計接口文檔:
獲取圖片驗證碼:/passport/login
請求方式 :POST json
請求參數:
mobile 手機號
password密碼
響應形式:json
代碼思路:
1.POST請求獲取手機號,密碼
2.校驗參數是否爲空
3.正則匹配驗證手機號格式是否正確
4.查詢數據庫取出手機號對應的用戶數據
5.檢查用戶是否存在,如果用戶不存在則報錯
6.校驗密碼,調用check_passord方法傳參對比
7.返回一個登錄結果
細節:
session記錄用戶狀態信息用於免密碼登錄
登錄後,記錄最新的登錄時間(當前時間對應的日期對象)
每次請求結束設置自動提交 在Config配置信息中寫入SQLALCHEMY_COMMIT_ON_TEARDOWN = True
SQLAlchemy的BUG,應該做異常處理
五、登錄信息顯示
從session中取出用戶的登錄狀態
判斷用戶是否登錄 根據session中是否記錄了user_id
根據user_id可以取出用戶的數據
user = user.to_dict() if user else None 傳入模板前,提前對數據格式進行封裝處理
將模型中的數據轉存到了字典中,並且封裝了數據的判斷和格式轉換
進行模板渲染
六、退出登錄
本質上其實就是 刪除session中的user_id
退出登錄:/logout
代碼實現
session.pop(“user_id”,None)
七、模型文件中的細節
default = datetime.now 設置字段的默認值爲當前時間
onupdate = datetime.now 記錄的更新時間,當記錄發生數據更新時,字段會更新爲onupdate 參數的值
db.DateTime 日期,數據必須對應爲日期對象
db.Boolean 布爾值
db.Enum( “MAN”,“WOMAN”)枚舉男女
db.Text 長文本 可達65535字節
八、新聞首頁-排行列表
接口分析
渲染方式:全局刷新/SEO–後端渲染–根路由
數據庫行爲:查詢 點擊量排行前10的新聞
代碼實現
在首頁路由中,查詢點擊量排行前十的新聞
rank_list = News.query.order_by(News.clicks.desc()).limit(10).all()
將排行數據傳入模板渲染
細節:
使用 自定義過濾器 來設置排行樣式
index_dict = {1:“first”,2:“second”,3:“third”}
return index_dict.get(index,"")
九、新聞首頁-獲取新聞列表
渲染方式:局部刷新–前端渲染–定義路由–返回數據
數據庫行爲:按照分類和頁面查詢新聞 按發佈時間倒序
數據庫行爲–請求參數–請求方式
渲染方式–相應形式
獲取新聞列表:/get_news_list
請求方式:GET
請求參數:
cid 分類id
cur_page 當前頁碼
per_count 每頁條數
響應形式 json
代碼實現:
獲取參數 cid、cur_page、per_count
校驗參數 判斷參數是否爲空
將字符串參數轉換爲int
數據庫行爲: 按照分類, 頁碼查詢新聞 發佈時間倒序
pn = News.query.filter_by(category_id=cid).order_by(News.create_time.desc()).paginate(cur_page,per_count)
返回數據