Python Web 开发高级应用指南
·
Python Web 开发高级应用指南
1. Web 开发基础
Python 的 Web 开发主要通过 Flask、Django 和 FastAPI 等框架实现。
# Flask 基础
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello():
return 'Hello, World!'
if __name__ == '__main__':
app.run(debug=True)
2. Flask 高级应用
2.1 蓝图
from flask import Flask, Blueprint
app = Flask(__name__)
# 创建蓝图
api_bp = Blueprint('api', __name__, url_prefix='/api')
# 注册路由
@api_bp.route('/users')
def get_users():
return {'users': ['Alice', 'Bob', 'Charlie']}
@api_bp.route('/users/<int:user_id>')
def get_user(user_id):
return {'user_id': user_id, 'name': f'User {user_id}'}
# 注册蓝图
app.register_blueprint(api_bp)
if __name__ == '__main__':
app.run(debug=True)
2.2 中间件
from flask import Flask, request
app = Flask(__name__)
# 中间件
@app.before_request
def before_request():
print(f"Request: {request.method} {request.url}")
@app.after_request
def after_request(response):
print(f"Response status: {response.status_code}")
return response
@app.route('/')
def hello():
return 'Hello, World!'
if __name__ == '__main__':
app.run(debug=True)
2.3 数据库集成
from flask import Flask, request, jsonify
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///example.db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db = SQLAlchemy(app)
# 定义模型
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(80), nullable=False)
email = db.Column(db.String(120), unique=True, nullable=False)
def to_dict(self):
return {
'id': self.id,
'name': self.name,
'email': self.email
}
# 创建数据库
with app.app_context():
db.create_all()
# 路由
@app.route('/users', methods=['GET', 'POST'])
def users():
if request.method == 'GET':
users = User.query.all()
return jsonify([user.to_dict() for user in users])
elif request.method == 'POST':
data = request.json
user = User(name=data['name'], email=data['email'])
db.session.add(user)
db.session.commit()
return jsonify(user.to_dict()), 201
@app.route('/users/<int:user_id>', methods=['GET', 'PUT', 'DELETE'])
def user(user_id):
user = User.query.get(user_id)
if not user:
return jsonify({'error': 'User not found'}), 404
if request.method == 'GET':
return jsonify(user.to_dict())
elif request.method == 'PUT':
data = request.json
user.name = data['name']
user.email = data['email']
db.session.commit()
return jsonify(user.to_dict())
elif request.method == 'DELETE':
db.session.delete(user)
db.session.commit()
return jsonify({'message': 'User deleted'})
if __name__ == '__main__':
app.run(debug=True)
3. Django 高级应用
3.1 视图类
# views.py
from django.views import View
from django.http import JsonResponse
from .models import User
class UserListView(View):
def get(self, request):
users = User.objects.all()
return JsonResponse([user.to_dict() for user in users], safe=False)
def post(self, request):
data = request.POST
user = User(name=data['name'], email=data['email'])
user.save()
return JsonResponse(user.to_dict(), status=201)
class UserDetailView(View):
def get(self, request, user_id):
try:
user = User.objects.get(id=user_id)
return JsonResponse(user.to_dict())
except User.DoesNotExist:
return JsonResponse({'error': 'User not found'}, status=404)
def put(self, request, user_id):
try:
user = User.objects.get(id=user_id)
data = request.POST
user.name = data['name']
user.email = data['email']
user.save()
return JsonResponse(user.to_dict())
except User.DoesNotExist:
return JsonResponse({'error': 'User not found'}, status=404)
def delete(self, request, user_id):
try:
user = User.objects.get(id=user_id)
user.delete()
return JsonResponse({'message': 'User deleted'})
except User.DoesNotExist:
return JsonResponse({'error': 'User not found'}, status=404)
# urls.py
from django.urls import path
from .views import UserListView, UserDetailView
urlpatterns = [
path('users/', UserListView.as_view()),
path('users/<int:user_id>/', UserDetailView.as_view()),
]
3.2 中间件
# middleware.py
class LoggingMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
print(f"Request: {request.method} {request.path}")
response = self.get_response(request)
print(f"Response status: {response.status_code}")
return response
# settings.py
MIDDLEWARE = [
'myapp.middleware.LoggingMiddleware',
# 其他中间件
]
3.3 信号
# signals.py
from django.db.models.signals import post_save
from django.dispatch import receiver
from .models import User
@receiver(post_save, sender=User)
def user_saved(sender, instance, created, **kwargs):
if created:
print(f"New user created: {instance.name}")
else:
print(f"User updated: {instance.name}")
# apps.py
from django.apps import AppConfig
class MyAppConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'myapp'
def ready(self):
import myapp.signals
4. FastAPI 高级应用
4.1 路径操作
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
from typing import List
app = FastAPI()
# 数据模型
class UserBase(BaseModel):
name: str
email: str
class UserCreate(UserBase):
pass
class User(UserBase):
id: int
class Config:
from_attributes = True
# 模拟数据库
users = []
# 路径操作
@app.post('/users/', response_model=User)
def create_user(user: UserCreate):
user_id = len(users) + 1
new_user = User(id=user_id, **user.dict())
users.append(new_user)
return new_user
@app.get('/users/', response_model=List[User])
def get_users():
return users
@app.get('/users/{user_id}', response_model=User)
def get_user(user_id: int):
for user in users:
if user.id == user_id:
return user
raise HTTPException(status_code=404, detail='User not found')
@app.put('/users/{user_id}', response_model=User)
def update_user(user_id: int, user: UserCreate):
for i, existing_user in enumerate(users):
if existing_user.id == user_id:
updated_user = User(id=user_id, **user.dict())
users[i] = updated_user
return updated_user
raise HTTPException(status_code=404, detail='User not found')
@app.delete('/users/{user_id}')
def delete_user(user_id: int):
for i, user in enumerate(users):
if user.id == user_id:
users.pop(i)
return {'message': 'User deleted'}
raise HTTPException(status_code=404, detail='User not found')
4.2 依赖注入
from fastapi import FastAPI, Depends, HTTPException
from pydantic import BaseModel
from typing import List
app = FastAPI()
# 数据模型
class UserBase(BaseModel):
name: str
email: str
class UserCreate(UserBase):
pass
class User(UserBase):
id: int
class Config:
from_attributes = True
# 模拟数据库
users = []
# 依赖项
def get_user_by_id(user_id: int):
for user in users:
if user.id == user_id:
return user
raise HTTPException(status_code=404, detail='User not found')
# 路径操作
@app.post('/users/', response_model=User)
def create_user(user: UserCreate):
user_id = len(users) + 1
new_user = User(id=user_id, **user.dict())
users.append(new_user)
return new_user
@app.get('/users/', response_model=List[User])
def get_users():
return users
@app.get('/users/{user_id}', response_model=User)
def get_user(user: User = Depends(get_user_by_id)):
return user
@app.put('/users/{user_id}', response_model=User)
def update_user(user_id: int, user: UserCreate, existing_user: User = Depends(get_user_by_id)):
for i, u in enumerate(users):
if u.id == user_id:
updated_user = User(id=user_id, **user.dict())
users[i] = updated_user
return updated_user
raise HTTPException(status_code=404, detail='User not found')
@app.delete('/users/{user_id}')
def delete_user(user_id: int, existing_user: User = Depends(get_user_by_id)):
for i, user in enumerate(users):
if user.id == user_id:
users.pop(i)
return {'message': 'User deleted'}
raise HTTPException(status_code=404, detail='User not found')
4.3 安全
from fastapi import FastAPI, Depends, HTTPException, status
from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm
from pydantic import BaseModel
from typing import Optional
import jwt
from datetime import datetime, timedelta
app = FastAPI()
# 配置
SECRET_KEY = "your-secret-key"
ALGORITHM = "HS256"
ACCESS_TOKEN_EXPIRE_MINUTES = 30
# 安全
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")
# 数据模型
class User(BaseModel):
username: str
email: Optional[str] = None
full_name: Optional[str] = None
disabled: Optional[bool] = None
class UserInDB(User):
hashed_password: str
class Token(BaseModel):
access_token: str
token_type: str
class TokenData(BaseModel):
username: Optional[str] = None
# 模拟用户数据库
users_db = {
"alice": {
"username": "alice",
"email": "alice@example.com",
"full_name": "Alice Smith",
"disabled": False,
"hashed_password": "fakehashedsecret"
},
"bob": {
"username": "bob",
"email": "bob@example.com",
"full_name": "Bob Brown",
"disabled": True,
"hashed_password": "fakehashedsecret2"
}
}
# 工具函数
def verify_password(plain_password, hashed_password):
return plain_password + "secret" == hashed_password
def get_user(db, username: str):
if username in db:
user_dict = db[username]
return UserInDB(**user_dict)
def authenticate_user(fake_db, username: str, password: str):
user = get_user(fake_db, username)
if not user:
return False
if not verify_password(password, user.hashed_password):
return False
return user
def create_access_token(data: dict, expires_delta: Optional[timedelta] = None):
to_encode = data.copy()
if expires_delta:
expire = datetime.utcnow() + expires_delta
else:
expire = datetime.utcnow() + timedelta(minutes=15)
to_encode.update({"exp": expire})
encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
return encoded_jwt
async def get_current_user(token: str = Depends(oauth2_scheme)):
credentials_exception = HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Could not validate credentials",
headers={"WWW-Authenticate": "Bearer"},
)
try:
payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
username: str = payload.get("sub")
if username is None:
raise credentials_exception
token_data = TokenData(username=username)
except jwt.PyJWTError:
raise credentials_exception
user = get_user(users_db, username=token_data.username)
if user is None:
raise credentials_exception
return user
async def get_current_active_user(current_user: User = Depends(get_current_user)):
if current_user.disabled:
raise HTTPException(status_code=400, detail="Inactive user")
return current_user
# 路径操作
@app.post("/token", response_model=Token)
async def login(form_data: OAuth2PasswordRequestForm = Depends()):
user = authenticate_user(users_db, form_data.username, form_data.password)
if not user:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Incorrect username or password",
headers={"WWW-Authenticate": "Bearer"},
)
access_token_expires = timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
access_token = create_access_token(
data={"sub": user.username}, expires_delta=access_token_expires
)
return {"access_token": access_token, "token_type": "bearer"}
@app.get("/users/me", response_model=User)
async def read_users_me(current_user: User = Depends(get_current_active_user)):
return current_user
5. 实际应用场景
5.1 RESTful API
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
from typing import List
app = FastAPI()
# 数据模型
class ItemBase(BaseModel):
name: str
description: str
price: float
tax: float = None
class ItemCreate(ItemBase):
pass
class Item(ItemBase):
id: int
class Config:
from_attributes = True
# 模拟数据库
items = []
# 路径操作
@app.post('/items/', response_model=Item)
def create_item(item: ItemCreate):
item_id = len(items) + 1
new_item = Item(id=item_id, **item.dict())
items.append(new_item)
return new_item
@app.get('/items/', response_model=List[Item])
def get_items():
return items
@app.get('/items/{item_id}', response_model=Item)
def get_item(item_id: int):
for item in items:
if item.id == item_id:
return item
raise HTTPException(status_code=404, detail='Item not found')
@app.put('/items/{item_id}', response_model=Item)
def update_item(item_id: int, item: ItemCreate):
for i, existing_item in enumerate(items):
if existing_item.id == item_id:
updated_item = Item(id=item_id, **item.dict())
items[i] = updated_item
return updated_item
raise HTTPException(status_code=404, detail='Item not found')
@app.delete('/items/{item_id}')
def delete_item(item_id: int):
for i, item in enumerate(items):
if item.id == item_id:
items.pop(i)
return {'message': 'Item deleted'}
raise HTTPException(status_code=404, detail='Item not found')
5.2 身份验证
from flask import Flask, request, jsonify, make_response
from flask_jwt_extended import JWTManager, create_access_token, jwt_required, get_jwt_identity
from werkzeug.security import generate_password_hash, check_password_hash
app = Flask(__name__)
app.config['JWT_SECRET_KEY'] = 'your-secret-key'
jwt = JWTManager(app)
# 模拟用户数据库
users = {
'alice': {
'username': 'alice',
'password': generate_password_hash('secret'),
'role': 'admin'
},
'bob': {
'username': 'bob',
'password': generate_password_hash('secret2'),
'role': 'user'
}
}
# 路由
@app.route('/login', methods=['POST'])
def login():
data = request.json
username = data.get('username')
password = data.get('password')
if not username or not password:
return jsonify({'error': 'Username and password required'}), 400
user = users.get(username)
if not user or not check_password_hash(user['password'], password):
return jsonify({'error': 'Invalid username or password'}), 401
access_token = create_access_token(identity=username)
return jsonify({'access_token': access_token}), 200
@app.route('/protected', methods=['GET'])
@jwt_required()
def protected():
current_user = get_jwt_identity()
return jsonify({'message': f'Hello, {current_user}!'}), 200
if __name__ == '__main__':
app.run(debug=True)
5.3 数据验证
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel, Field
from typing import List
app = FastAPI()
# 数据模型
class UserBase(BaseModel):
name: str = Field(..., min_length=1, max_length=50)
email: str = Field(..., regex=r'^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$')
age: int = Field(..., ge=1, le=120)
class UserCreate(UserBase):
password: str = Field(..., min_length=6)
class User(UserBase):
id: int
class Config:
from_attributes = True
# 模拟数据库
users = []
# 路径操作
@app.post('/users/', response_model=User)
def create_user(user: UserCreate):
# 检查邮箱是否已存在
for existing_user in users:
if existing_user.email == user.email:
raise HTTPException(status_code=400, detail='Email already registered')
user_id = len(users) + 1
new_user = User(id=user_id, name=user.name, email=user.email, age=user.age)
users.append(new_user)
return new_user
@app.get('/users/', response_model=List[User])
def get_users():
return users
6. 最佳实践
- 选择合适的框架:根据项目需求选择合适的 Web 框架。
- RESTful API 设计:遵循 RESTful API 设计原则,使用适当的 HTTP 方法和状态码。
- 数据验证:使用 Pydantic 或 Django 表单进行数据验证。
- 安全:实现适当的身份验证和授权机制。
- 数据库设计:设计合理的数据库 schema,使用 ORM 进行数据库操作。
- 错误处理:统一处理错误,返回友好的错误信息。
- 测试:编写单元测试和集成测试,确保代码质量。
- 部署:使用适当的部署策略,如容器化、负载均衡等。
7. 总结
Python 的 Web 开发框架提供了丰富的功能,从基本的路由和视图到高级的中间件、依赖注入和安全机制。通过掌握这些高级应用,我们可以构建更加健壮、安全、可维护的 Web 应用。
在实际应用中,Web 开发可以用于构建 RESTful API、身份验证系统、数据验证等多种场景,满足不同的业务需求。
希望本文对你理解和应用 Python Web 开发有所帮助!
更多推荐



所有评论(0)