flask-expert
Included with Lifetime
$97 forever
Expert-level Flask web development, REST APIs, extensions, and production deployment
frameworksflaskpythonweb-frameworkrest-apijinja2
What this skill does
# Flask Expert
Expert guidance for Flask web development, building REST APIs, using extensions, and production deployment.
## Core Concepts
### Flask Fundamentals
- Routing and views
- Request/response handling
- Templates with Jinja2
- Blueprints for modularity
- Application factory pattern
- Configuration management
### Flask Extensions
- Flask-SQLAlchemy (ORM)
- Flask-Migrate (database migrations)
- Flask-Login (authentication)
- Flask-RESTful (REST APIs)
- Flask-JWT-Extended (JWT tokens)
- Flask-CORS (CORS handling)
- Flask-Limiter (rate limiting)
### Best Practices
- Application structure
- Error handling
- Testing
- Security
- Production deployment
## Basic Flask Application
```python
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):
self.password_hash = generate_password_hash(password)
def check_password(self, password):
return check_password_hash(self.password_hash, password)
def to_dict(self):
return {
'id': self.id,
'email': self.email,
'created_at': self.created_at.isoformat()
}
class Post(db.Model):
__tablename__ = 'posts'
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(200), nullable=False)
content = db.Column(db.Text, nullable=False)
user_id = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=False)
created_at = db.Column(db.DateTime, default=datetime.utcnow)
def to_dict(self):
return {
'id': self.id,
'title': self.title,
'content': self.content,
'author': self.author.to_dict(),
'created_at': self.created_at.isoformat()
}
```
## REST API with Flask-RESTful
```python
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):
@marshal_with(user_fields)
def get(self):
"""Get all users"""
page = request.args.get('page', 1, type=int)
per_page = request.args.get('per_page', 20, type=int)
users = User.query.paginate(page=page, per_page=per_page)
return users.items
def post(self):
"""Create new user"""
args = user_parser.parse_args()
if User.query.filter_by(email=args['email']).first():
return {'message': 'Email already exists'}, 400
user = User(email=args['email'])
user.set_password(args['password'])
db.session.add(user)
db.session.commit()
return user.to_dict(), 201
class UserResource(Resource):
@marshal_with(user_fields)
def get(self, user_id):
"""Get user by ID"""
user = User.query.get_or_404(user_id)
return user
@jwt_required()
def delete(self, user_id):
"""Delete user"""
current_user_id = get_jwt_identity()
if current_user_id != user_id:
return {'message': 'Unauthorized'}, 403
user = User.query.get_or_404(user_id)
db.session.delete(user)
db.session.commit()
return '', 204
class PostListResource(Resource):
@marshal_with(post_fields)
def get(self):
"""Get all posts"""
posts = Post.query.order_by(Post.created_at.desc()).all()
return posts
@jwt_required()
def post(self):
"""Create new post"""
args = post_parser.parse_args()
current_user_id = get_jwt_identity()
post = Post(
title=args['title'],
content=args['content'],
user_id=current_user_id
)
db.session.add(post)
db.session.commit()
return post.to_dict(), 201
# Register resources
api.add_resource(UserListResource, '/users')
api.add_resource(UserResource, '/users/<int:user_id>')
api.add_resource(PostListResource, '/posts')
```
## Authentication with JWT
```python
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('email') or not data.get('password'):
return jsonify({'message': 'Missing credentials'}), 400
user = User.query.filter_by(email=data['email']).first()
if not user or not user.check_password(data['password']):
return jsonify({'message': 'Invalid credentials'}), 401
access_token = create_access_token(identity=user.id)
refresh_token = create_refresh_token(identity=user.id)
return jsonify({
'access_token': access_token,
'refresh_token': refresh_token,
'user': user.to_dict()
}), 200
@auth_bp.route('/refresh', methods=['POST'])
@jwt_required(refresh=True)
def refresh():
"""Refresh access token"""
current_user_id = get_jwt_identity()
access_token = create_access_token(identity=current_user_id)
return jsonify({'access_token': access_token}), 200
@auth_bp.route('/me', methods=['GET'])
@jwt_required()
def get_current_user():
"""Get current authenticated user"""
current_user_id = get_jwt_identity()
user = User.query.get_or_404(current_user_id)
return jsonify(user.to_dict()), 200
```
## Error Handling
```python
from flask import jsonify
from sqlalchemy.exc iRelated in frameworks
react-expert
IncludedExpert-level React development with hooks, performance optimization, state management, and modern patterns
frameworks
spring-boot-expert
IncludedExpert-level Spring Boot, Spring Framework, REST APIs, and microservices development
frameworks
django-expert
IncludedExpert-level Django development for robust Python web applications with ORM, admin, and authentication
frameworks