用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
直接命令不会经过审查 Prompt;运行前请先检查来源。
npx skills add https://github.com/personamanagmentlayer/pcl --skill flask-expert命令会保持在同一行。复制前请横向滚动并检查完整内容。
想先保存到本地?可下载 SkillsMP 当前能够提供的文件。
正在显示 SKILL.md
| name | flask-expert |
| version | 1.0.0 |
| description | Expert-level Flask web development, REST APIs, extensions, and production deployment |
| category | frameworks |
| tags | ["flask","python","web-framework","rest-api","jinja2"] |
| allowed-tools | ["Read","Write","Edit","Bash(flask:*, python:*)"] |
Expert guidance for Flask web development, building REST APIs, using extensions, and production deployment.
from flask import Flask, request, jsonify, render_template
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate
from werkzeug.security import generate_password_hash, check_password_hash
from datetime import datetime
# Application factory
def create_app(config_name='development'):
app = Flask(__name__)
app.config.from_object(config[config_name])
# Initialize extensions
db.init_app(app)
migrate.init_app(app, db)
# Register blueprints
from .api import api_bp
app.register_blueprint(api_bp, url_prefix='/api')
from .auth import auth_bp
app.register_blueprint(auth_bp, url_prefix='/auth')
return app
# Database setup
db = SQLAlchemy()
migrate = Migrate()
# Models
class User(db.Model):
__tablename__ = 'users'
id = db.Column(db.Integer, primary_key=True)
email = db.Column(db.String(120), unique=True, nullable=False)
password_hash = db.Column(db.String(255), nullable=False)
created_at = db.Column(db.DateTime, default=datetime.utcnow)
posts = db.relationship('Post', backref='author', lazy='dynamic')
def set_password(self, password):
.password_hash = generate_password_hash(password)
():
check_password_hash(.password_hash, password)
():
{
: .,
: .email,
: .created_at.isoformat()
}
(db.Model):
__tablename__ =
= db.Column(db.Integer, primary_key=)
title = db.Column(db.String(), nullable=)
content = db.Column(db.Text, nullable=)
user_id = db.Column(db.Integer, db.ForeignKey(), nullable=)
created_at = db.Column(db.DateTime, default=datetime.utcnow)
():
{
: .,
: .title,
: .content,
: .author.to_dict(),
: .created_at.isoformat()
}
from flask import Blueprint
from flask_restful import Api, Resource, reqparse, fields, marshal_with
from flask_jwt_extended import jwt_required, get_jwt_identity
from .models import db, User, Post
api_bp = Blueprint('api', __name__)
api = Api(api_bp)
# Request parsers
user_parser = reqparse.RequestParser()
user_parser.add_argument('email', type=str, required=True, help='Email is required')
user_parser.add_argument('password', type=str, required=True, help='Password is required')
post_parser = reqparse.RequestParser()
post_parser.add_argument('title', type=str, required=True)
post_parser.add_argument('content', type=str, required=True)
# Response marshalling
user_fields = {
'id': fields.Integer,
'email': fields.String,
'created_at': fields.DateTime(dt_format='iso8601')
}
post_fields = {
'id': fields.Integer,
'title': fields.String,
'content': fields.String,
'author': fields.Nested(user_fields),
'created_at': fields.DateTime(dt_format='iso8601')
}
# Resources
class UserListResource(Resource):
():
page = request.args.get(, , =)
per_page = request.args.get(, , =)
users = User.query.paginate(page=page, per_page=per_page)
users.items
():
args = user_parser.parse_args()
User.query.filter_by(email=args[]).first():
{: },
user = User(email=args[])
user.set_password(args[])
db.session.add(user)
db.session.commit()
user.to_dict(),
():
():
user = User.query.get_or_404(user_id)
user
():
current_user_id = get_jwt_identity()
current_user_id != user_id:
{: },
user = User.query.get_or_404(user_id)
db.session.delete(user)
db.session.commit()
,
():
():
posts = Post.query.order_by(Post.created_at.desc()).()
posts
():
args = post_parser.parse_args()
current_user_id = get_jwt_identity()
post = Post(
title=args[],
content=args[],
user_id=current_user_id
)
db.session.add(post)
db.session.commit()
post.to_dict(),
api.add_resource(UserListResource, )
api.add_resource(UserResource, )
api.add_resource(PostListResource, )
from flask import Blueprint, request, jsonify
from flask_jwt_extended import (
JWTManager, create_access_token, create_refresh_token,
jwt_required, get_jwt_identity
)
from .models import db, User
auth_bp = Blueprint('auth', __name__)
jwt = JWTManager()
@auth_bp.route('/register', methods=['POST'])
def register():
"""Register new user"""
data = request.get_json()
if not data or not data.get('email') or not data.get('password'):
return jsonify({'message': 'Missing required fields'}), 400
if User.query.filter_by(email=data['email']).first():
return jsonify({'message': 'Email already exists'}), 400
user = User(email=data['email'])
user.set_password(data['password'])
db.session.add(user)
db.session.commit()
return jsonify(user.to_dict()), 201
@auth_bp.route('/login', methods=['POST'])
def login():
"""Login user"""
data = request.get_json()
if not data or not data.get() data.get():
jsonify({: }),
user = User.query.filter_by(email=data[]).first()
user user.check_password(data[]):
jsonify({: }),
access_token = create_access_token(identity=user.)
refresh_token = create_refresh_token(identity=user.)
jsonify({
: access_token,
: refresh_token,
: user.to_dict()
}),
():
current_user_id = get_jwt_identity()
access_token = create_access_token(identity=current_user_id)
jsonify({: access_token}),
():
current_user_id = get_jwt_identity()
user = User.query.get_or_404(current_user_id)
jsonify(user.to_dict()),
from flask import jsonify
from sqlalchemy.exc import IntegrityError
from werkzeug.exceptions import HTTPException
def register_error_handlers(app):
"""Register error handlers"""
@app.errorhandler(HTTPException)
def handle_http_exception(e):
"""Handle HTTP exceptions"""
return jsonify({
'error': e.name,
'message': e.description,
'code': e.code
}), e.code
@app.errorhandler(IntegrityError)
def handle_integrity_error(e):
"""Handle database integrity errors"""
db.session.rollback()
return jsonify({
'error': 'Database error',
'message': 'A database constraint was violated'
}), 400
@app.errorhandler(Exception)
def handle_exception(e):
"""Handle unexpected exceptions"""
app.logger.exception(e)
return jsonify({
'error': 'Internal server error',
'message': 'An unexpected error occurred'
}), 500
@app.errorhandler()
():
jsonify({
: ,
:
}),
():
jsonify({
: ,
:
}),
from flask_limiter import Limiter
from flask_limiter.util import get_remote_address
limiter = Limiter(
key_func=get_remote_address,
default_limits=["200 per day", "50 per hour"],
storage_uri="redis://localhost:6379"
)
def create_app():
app = Flask(__name__)
limiter.init_app(app)
@app.route('/api/search')
@limiter.limit("10 per minute")
def search():
"""Rate-limited search endpoint"""
query = request.args.get('q')
# Perform search
return jsonify({'results': []})
@app.route('/api/expensive')
@limiter.limit("1 per minute")
def expensive_operation():
"""Very rate-limited expensive operation"""
# Expensive computation
return jsonify({'status': 'completed'})
return app
import os
class Config:
"""Base configuration"""
SECRET_KEY = os.environ.get('SECRET_KEY') or 'dev-secret-key'
SQLALCHEMY_TRACK_MODIFICATIONS = False
JWT_SECRET_KEY = os.environ.get('JWT_SECRET_KEY') or 'jwt-secret-key'
JWT_ACCESS_TOKEN_EXPIRES = 3600 # 1 hour
JWT_REFRESH_TOKEN_EXPIRES = 2592000 # 30 days
class DevelopmentConfig(Config):
"""Development configuration"""
DEBUG = True
SQLALCHEMY_DATABASE_URI = 'sqlite:///dev.db'
class TestingConfig(Config):
"""Testing configuration"""
TESTING = True
SQLALCHEMY_DATABASE_URI = 'sqlite:///:memory:'
class ProductionConfig(Config):
"""Production configuration"""
DEBUG = False
SQLALCHEMY_DATABASE_URI = os.environ.get('DATABASE_URL')
config = {
'development': DevelopmentConfig,
'testing': TestingConfig,
'production': ProductionConfig,
'default': DevelopmentConfig
}
import pytest
from app import create_app, db
from app.models import User
@pytest.fixture
def app():
"""Create application for testing"""
app = create_app('testing')
with app.app_context():
db.create_all()
yield app
db.session.remove()
db.drop_all()
@pytest.fixture
def client(app):
"""Create test client"""
return app.test_client()
@pytest.fixture
def auth_headers(client):
"""Create authenticated headers"""
# Register user
client.post('/auth/register', json={
'email': 'test@example.com',
'password': 'password123'
})
# Login
response = client.post('/auth/login', json={
'email': 'test@example.com',
'password': 'password123'
})
token = response.json['access_token']
return {'Authorization': f'Bearer {token}'}
def test_register_user(client):
"""Test user registration"""
response = client.post('/auth/register', json={
'email': ,
:
})
response.status_code ==
response.json[] ==
():
client.post(, json={
: ,
:
})
response = client.post(, json={
: ,
:
})
response.status_code ==
response.json
():
response = client.post(,
json={
: ,
:
},
headers=auth_headers
)
response.status_code ==
response.json[] ==
():
response = client.get()
response.status_code ==
(response.json, )
# wsgi.py
from app import create_app
import os
app = create_app(os.getenv('FLASK_ENV', 'production'))
if __name__ == '__main__':
app.run()
# Using Gunicorn
gunicorn -w 4 -b 0.0.0.0:8000 wsgi:app
# With proper workers
gunicorn -w 4 \
--worker-class gevent \
--worker-connections 1000 \
--timeout 30 \
--keep-alive 5 \
--log-level info \
--access-logfile - \
--error-logfile - \
wsgi:app
❌ Global app instance ❌ No database migrations ❌ Hardcoded configuration ❌ Missing error handling ❌ No authentication ❌ Exposing sensitive data ❌ Not using blueprints
基于 SOC 职业分类