網(wǎng)絡(luò)營銷做私活網(wǎng)站智慧軟文發(fā)稿平臺官網(wǎng)
前言
Flask是一個用Python編寫的輕量級Web應(yīng)用框架。它最初由Armin Ronacher作為Werkzeug的一個子項目在2010年開發(fā)出來。Werkzeug是一個綜合工具包,提供了各種用于Web應(yīng)用開發(fā)的工具和函數(shù)。自發(fā)布以來,Flask因其簡潔和靈活性而迅速受到開發(fā)者的歡迎。隨著Python社區(qū)的增長,Flask也得到了不斷的更新和改進,成為了Python Web開發(fā)中的主流框架之一。它擁有龐大的用戶和貢獻者社區(qū)。
除此之外,于當(dāng)下大模型大爆發(fā)的時代,它是也非常適合給企業(yè)做私有大模型場景提供web頁面。對于web初學(xué)者來說一個非常值得嘗試的框架。
接下來我們從web基礎(chǔ)概念、flask安裝調(diào)試、路由、模版、藍圖、數(shù)據(jù)庫操作、實戰(zhàn)案例幾個方面給大家介紹flask的使用。
一、Web應(yīng)用基本概念
如果你是第一次開發(fā)Web應(yīng)用程序,你需要首選了解一下幾個概念,它們是IP地址、dns、url、http、https。
1. IP地址
IP地址是分配給網(wǎng)絡(luò)上每個設(shè)備的唯一標(biāo)識符。
它允許設(shè)備之間進行通信,分為IPv4和IPv6兩種類型。
2. DNS(域名系統(tǒng))
DNS是互聯(lián)網(wǎng)上用于將域名轉(zhuǎn)換為IP地址的系統(tǒng)。
它允許用戶通過易于記憶的域名來訪問網(wǎng)站,而不是記住復(fù)雜的數(shù)字IP地址。
3. URL(統(tǒng)一資源定位符)
它是互聯(lián)網(wǎng)上資源的地址,包括網(wǎng)頁、圖片、視頻等。
格式通常為:協(xié)議://域名:端口/路徑?查詢字符串#片段標(biāo)識符。
4. HTTP(超文本傳輸協(xié)議)
HTTP是用于從Web服務(wù)器傳輸超文本到本地瀏覽器的協(xié)議。
它是Web通信的基礎(chǔ),支持客戶端和服務(wù)器之間的請求和響應(yīng)。
5. HTTPS(安全超文本傳輸協(xié)議)
HTTPS是HTTP的安全版本,通過SSL/TLS協(xié)議加密數(shù)據(jù)傳輸。
它保護數(shù)據(jù)免受中間人攻擊和其他安全威脅。
以上這樣介紹可能不夠直觀,舉一些例子吧。
一個小姐姐去北京西單吃北京烤鴨,她要去的那家烤鴨店的名字就是域名,比如我們平時在瀏覽器里輸入的taobaoc.om。而這家烤鴨店的地址門牌號就是IP,烤鴨店名和地址都在工商局有注冊,這個工商局就是DNS服務(wù)器。URL是由域名和訪問資源組成的。比如taobao.com/xxxxx. 這個xxxxx就是資源,你可以理解為烤鴨店里具體的包間或卡座以及烤鴨店提供的服務(wù)。
http和https的概念你可以理解成寫信和和回信的過程,http就是沒有加密的信件,一個人投訴物業(yè)給有關(guān)部門寫信,主管部門收到后把處理結(jié)果回信這個寫信的人。https就是加密的信件,比如諜戰(zhàn)片里的特工,特工給上級寫的信都是用的暗語,即使信件傳遞過程有人拆開了信,也是看不懂信中的暗語的。在實際web的通信過程中,http和https傳遞的都是具有特定格式的文本信息,瀏覽器發(fā)起一個請求后,服務(wù)器端會做出響應(yīng)把操作結(jié)果反饋給瀏覽器端。這個響應(yīng)可能是查詢數(shù)據(jù)、刪除數(shù)據(jù)或者新增數(shù)據(jù)。而服務(wù)器會返回瀏覽器的數(shù)據(jù)通常是可以直接渲染的html和css或是可以被間接渲染的json、xml等。
二、Flask安裝和調(diào)試
2.1Flask安裝
首選在pytcharm里建一個python項目,然后通過命令行切換到該項目的虛擬環(huán)境。這里如何安裝和使用虛擬環(huán)境參考《Anaconda的安裝和使用》,如何正確使用PyCharm創(chuàng)建python參考《PyCharm新手入門》。
在虛擬環(huán)境輸入
pip install Flask
2.2Flask調(diào)試
1. 在項目中創(chuàng)建一個app.py的文件。
代碼如下:
from flask import Flaskapp = Flask(__name__)
@app.route('/')
def hello_world():usr='老王';print(f'{usr}已經(jīng)創(chuàng)建好了第一個flask應(yīng)用!');return 'Hello, World!'
if __name__ == '__main__':app.run(debug=True)
2. 設(shè)置一下flask項目的調(diào)試環(huán)境
3. 調(diào)試報錯
配置好調(diào)試環(huán)境,打一個斷點如下圖,然后用快捷鍵【shift+F9】啟動調(diào)試。
調(diào)試啟動后,可以看到控制臺給出一個訪問地址http://127.0.0.1:5000。復(fù)制這個url地址在瀏覽器里打開。
瀏覽器打開后,如果app.py這個程序進入調(diào)試狀態(tài),按F8可以進入分步調(diào)試了。這意味著你可以正常調(diào)試flask應(yīng)用了,當(dāng)完成調(diào)試后,你在瀏覽器看到“Hello, World!”。這里恭喜你,你已經(jīng)很順利的配置環(huán)境,可以進入開發(fā)的階段了。
然而事情的實際進展不會這么順利。你可能會遇到環(huán)境報錯,就像我遇到的情況。
剛一點擊shift+F9就報錯
[Errno 2] No such file or directory
經(jīng)查網(wǎng)上查找資料,發(fā)現(xiàn)最后問題出在安裝flask版本的問題上,把flask版本調(diào)整為2.0,3就可以解決問題。查看flask版本
pip show flask
發(fā)現(xiàn)flask版本是3.0.2,。重新安裝flask
pip uninstall flask
pip install flask==2.0.3
調(diào)整版本后重新再次啟動,不再報錯,然后再次shift+F9啟動調(diào)試,這次沒有報錯,但是調(diào)試啟動后進入helpers.py ,再點擊F8,繼續(xù)調(diào)試報以下錯誤:
d:\conda_envs\pycharm\python.exe "D:/Program Files/PyCharm Community Edition 2023.2.3/plugins/python-ce/helpers/pydev/pydevd.py" --multiprocess --qt-support=auto --client 127.0.0.1 --port 3269 --file D:\python_workspace\pythonProject\app.py
已連接到 pydev 調(diào)試器(內(nèi)部版本號 232.10072.31)Traceback (most recent call last):File "<frozen importlib._bootstrap>", line 1027, in _find_and_loadFile "<frozen importlib._bootstrap>", line 1006, in _find_and_load_unlockedFile "<frozen importlib._bootstrap>", line 688, in _load_unlockedFile "<frozen importlib._bootstrap_external>", line 883, in exec_moduleFile "<frozen importlib._bootstrap>", line 241, in _call_with_frames_removedFile "d:\conda_envs\pycharm\lib\site-packages\flask\__init__.py", line 7, in <module>from .app import Flask as FlaskFile "d:\conda_envs\pycharm\lib\site-packages\flask\app.py", line 28, in <module>from . import cliFile "d:\conda_envs\pycharm\lib\site-packages\flask\cli.py", line 18, in <module>from .helpers import get_debug_flagFile "d:\conda_envs\pycharm\lib\site-packages\flask\helpers.py", line 16, in <module>from werkzeug.urls import url_quote
ImportError: cannot import name 'url_quote' from 'werkzeug.urls' (d:\conda_envs\pycharm\lib\site-packages\werkzeug\urls.py)
python-BaseException
經(jīng)上網(wǎng)查找問題,發(fā)現(xiàn)是werkzeug的版本仍然有問題,因為werkzeug是在安裝flask時同時關(guān)聯(lián)安裝的。我們雖然重新安裝了flask,但是werkzeug仍然是舊版本,于是重新安裝werkzeug
pip uninstall werkzeug
pip install werkzeug==2.0.3
重新調(diào)試程序,shift+F9,F8。一切正常。這里分享一個經(jīng)驗給大家,在我們運行python開源項目的時候,包括大模型應(yīng)用像stable diffusion、llama等,我們遇到的問題80%甚至是98%都是因為安裝的庫文件版本有問題。所以安裝python庫的時候最好搞清楚庫的版本,否則你會遇到數(shù)不盡的麻煩。
二、路由和視圖函數(shù)
在Flask中,路由由@app.route()裝飾器定義,視圖函數(shù)是處理請求并返回響應(yīng)的函數(shù)。
@app.route('/user/<username>')
def show_user_profile(username):# 通過URL中的參數(shù)訪問用戶信息return f'User {username}'@app.route('/post/<int:post_id>')
def show_post(post_id):# 通過URL中的參數(shù)訪問帖子信息,確保參數(shù)是整數(shù)類型return f'Post {post_id}'
三、藍圖:
在 Flask 中,通常將不同的服務(wù)請求(即不同的路由和視圖函數(shù))組織在一個 Python 文件中是可行的,尤其是在小型應(yīng)用或者學(xué)習(xí)階段。然而,對于更大的應(yīng)用或更好的代碼組織,你可能希望將不同的服務(wù)請求拆分到不同的模塊或藍圖中。
以下是一些組織服務(wù)請求的一般建議:
1.單一文件應(yīng)用:
在小型應(yīng)用中,將所有的服務(wù)請求都寫在一個文件中是可以的,這樣簡單明了。例如:
from flask import Flask
app = Flask(__name__)
@app.route('/')
def home():return 'Home Page'@app.route('/about')
def about():return 'About Page'if __name__ == '__main__':app.run(debug=True)
2.模塊化組織:
將相關(guān)的服務(wù)請求分組到不同的模塊中,例如 views.py:
# views.py
from flask import Blueprintmain_bp = Blueprint('main', __name__)@main_bp.route('/')
def home():return 'Home Page'@main_bp.route('/about')
def about():return 'About Page'
然后在主應(yīng)用中導(dǎo)入并注冊這個藍圖:
3.藍圖
請求組織到不同的藍圖中。藍圖是一種更高級別的組織方式,用于將應(yīng)用拆分為可維護的模塊。例如:
# main_blueprint.py
from flask import Blueprintmain_bp = Blueprint('main', __name__)@main_bp.route('/')
def home():return 'Home Page'@main_bp.route('/about')
def about():return 'About Page'
主應(yīng)用
# main_blueprint.py
from flask import Blueprintmain_bp = Blueprint('main', __name__)@main_bp.route('/')
def home():return 'Home Page'@main_bp.route('/about')
def about():return 'About Page'
這些都是一些通用的組織代碼的方式,具體選擇取決于你的應(yīng)用規(guī)模和組織結(jié)構(gòu)。在項目變得更大時,使用模塊化的方式可以更好地保持代碼的可維護性。
四、表單處理:
Flask可以輕松處理表單提交。使用request對象從POST請求中獲取表單數(shù)據(jù),或使用flask-wtf等擴展庫來簡化表單處理。
from flask import Flask, render_template, request@app.route('/login', methods=['POST', 'GET'])
def login():if request.method == 'POST':username = request.form['username']password = request.form['password']# 處理表單提交的數(shù)據(jù)return f'Username: {username}, Password: {password}'return render_template('login.html')
五、Jinqa模版
在 Flask 中,你可以使用模板引擎來實現(xiàn)動態(tài)頁面。模板引擎允許你在 HTML 文件中嵌入動態(tài)內(nèi)容,從而根據(jù)不同的請求動態(tài)生成頁面。Flask 默認使用 Jinja2 模板引擎,它提供了靈活的語法和功能,方便在 HTML 中插入動態(tài)內(nèi)容。
1.安裝 Jinja2:
如果你是在新的虛擬環(huán)境中,你需要安裝 Jinja2:
pip install Jinja2
2.創(chuàng)建 Flask 應(yīng)用:
from flask import Flask, render_templateapp = Flask(__name__)@app.route('/')
def home():# 傳遞動態(tài)數(shù)據(jù)到模板user = {'username': 'John', 'age': 25}return render_template('home.html', user=user)if __name__ == '__main__':app.run(debug=True)
3.創(chuàng)建模板文件:
在你的項目目錄下創(chuàng)建一個名為 templates 的文件夾,然后在該文件夾中創(chuàng)建 home.html 文件:
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Dynamic Page</title>
</head>
<body><h1>Welcome, {{ user.username }}!</h1><p>Your age is {{ user.age }}.</p>
</body>
</html>
在這個例子中,{{ user.username }} 和 {{ user.age }} 是模板中的變量,它們將在運行時由 Flask 填充為相應(yīng)的值。
六、操作數(shù)據(jù)庫
1.sqlite3模塊
SQLite 是一個自包含、無服務(wù)器、零配置的 SQL 數(shù)據(jù)庫引擎。它是 Python 標(biāo)準(zhǔn)庫的一部分,所以在大多數(shù)情況下,你不需要手動安裝 SQLite 數(shù)據(jù)庫,因為它已經(jīng)包含在 Python 的 sqlite3 模塊中。
在 Python 中,你可以使用標(biāo)準(zhǔn)庫中的 sqlite3 模塊來訪問 SQLite 數(shù)據(jù)庫:
import sqlite3
# 連接到 SQLite 數(shù)據(jù)庫(如果數(shù)據(jù)庫不存在,會自動創(chuàng)建)
conn = sqlite3.connect('example.db')
# 創(chuàng)建一個游標(biāo)對象
cursor = conn.cursor()
# 執(zhí)行 SQL 語句
cursor.execute('CREATE TABLE IF NOT EXISTS users (id INTEGER PRIMARY KEY, name TEXT, age INTEGER)')
# 插入數(shù)據(jù)
cursor.execute('INSERT INTO users (name, age) VALUES (?, ?)', ('Alice', 30))
# 提交事務(wù)
conn.commit()
# 查詢數(shù)據(jù)
cursor.execute('SELECT * FROM users')
print(cursor.fetchall())
# 關(guān)閉連接
conn.close()
這個示例展示了如何使用 Python 的 sqlite3 模塊來創(chuàng)建表、插入數(shù)據(jù)和查詢數(shù)據(jù)。你可以直接在你的 Python 環(huán)境中運行這個代碼來測試 SQLite 數(shù)據(jù)庫的基本功能。
2.使用SQLAlchemy模塊訪問數(shù)據(jù)庫
除了python自帶的標(biāo)準(zhǔn)sqlite3模塊,還可以通過SQLAlchemy 來處理和數(shù)據(jù)庫交互,不同的是,這個模塊除了sqlite還可以訪問mysql等其他數(shù)據(jù)庫。
使用SQLAlchemy操作數(shù)據(jù)庫的步驟
安裝依賴
pip install Flask SQLAlchemy
創(chuàng)建 Flask 應(yīng)用
1. 項目結(jié)構(gòu)
/flask_app├── app.py├── models.py└── templates└── index.html
2.models.py - 定義數(shù)據(jù)庫模型
from flask_sqlalchemy import SQLAlchemydb = SQLAlchemy()class User(db.Model):id = db.Column(db.Integer, primary_key=True)name = db.Column(db.String(80), nullable=False)age = db.Column(db.Integer, nullable=False)def __repr__(self):return f'<User {self.name}>'
3 .app.py - 主應(yīng)用文件
from flask import Flask, request, jsonify, render_template
from models import db, Userapp = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///example.db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = Falsedb.init_app(app)@app.route('/')
def index():users = User.query.all()return render_template('index.html', users=users)@app.route('/user', methods=['POST'])
def create_user():data = request.get_json()new_user = User(name=data['name'], age=data['age'])db.session.add(new_user)db.session.commit()return jsonify({'message': 'User created'}), 201@app.route('/user/<int:id>', methods=['GET'])
def get_user(id):user = User.query.get_or_404(id)return jsonify({'id': user.id, 'name': user.name, 'age': user.age})@app.route('/user/<int:id>', methods=['PUT'])
def update_user(id):data = request.get_json()user = User.query.get_or_404(id)user.name = data.get('name', user.name)user.age = data.get('age', user.age)db.session.commit()return jsonify({'message': 'User updated'})@app.route('/user/<int:id>', methods=['DELETE'])
def delete_user(id):user = User.query.get_or_404(id)db.session.delete(user)db.session.commit()return jsonify({'message': 'User deleted'})if __name__ == '__main__':with app.app_context():db.create_all()app.run(debug=True)
4 .templates/index.html - 用于顯示用戶列表的簡單 HTML 模板
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>User List</title>
</head>
<body><h1>User List</h1><ul>{% for user in users %}<li>{{ user.name }} ({{ user.age }} years old)</li>{% endfor %}</ul>
</body>
</html>