第19篇:python高级编程进阶:使用Flask进行Web开发
第19篇:python高级编程进阶:使用Flask进行Web开发
内容简介
在第18篇文章中,我们介绍了Web开发的基础知识,并使用Flask框架构建了一个简单的Web应用。本篇文章将深入探讨Flask的高级功能,涵盖模板引擎(Jinja2)、表单处理、数据库集成以及用户认证等主题。通过系统的讲解和实战案例,您将掌握构建功能更为丰富和复杂的Web应用所需的技能。
目录
- Flask的深入使用
- Flask扩展
- 蓝图(Blueprints)
- 应用工厂模式
- 模板引擎(Jinja2)
- Jinja2简介
- 模板继承
- 控制结构
- 宏与自定义过滤器
- 表单处理
- 使用Flask-WTF
- 表单验证
- 处理表单数据
- 数据库集成
- 使用Flask-SQLAlchemy
- 数据库迁移
- 关系数据库操作
- 用户认证
- 使用Flask-Login
- 用户注册与登录
- 权限管理
- 示例项目:博客系统
- 项目结构
- 实现用户认证
- 创建和管理博客文章
- 评论功能
- 常见问题及解决方法
- 问题1:如何处理表单的CSRF保护?
- 问题2:如何优化数据库查询性能?
- 问题3:如何实现密码的安全存储?
- 问题4:如何部署Flask应用到生产环境?
- 总结
Flask的深入使用
Flask扩展
Flask的强大之处在于其丰富的扩展生态系统,这些扩展能够为您的应用添加各种功能,如数据库集成、表单处理、用户认证等。常用的Flask扩展包括:
- Flask-WTF:集成了WTForms,用于表单处理和验证。
- Flask-Login:用于用户认证和会话管理。
- Flask-Migrate:基于Alembic的数据库迁移工具。
- Flask-Mail:用于发送电子邮件。
- Flask-Admin:提供管理后台界面。
- Flask-RESTful:用于构建RESTful API。
蓝图(Blueprints)
蓝图是Flask中组织大型应用的一种方式。它允许您将应用的不同部分拆分成独立的组件或模块,从而提高代码的可维护性和可扩展性。
创建蓝图的步骤:
-
定义蓝图:
# blog/routes.py from flask import Blueprint, render_templateblog_bp = Blueprint('blog', __name__, url_prefix='/blog')@blog_bp.route('/') def index():return render_template('blog/index.html')
-
注册蓝图:
# app.py from flask import Flask from blog.routes import blog_bpapp = Flask(__name__) app.register_blueprint(blog_bp)if __name__ == '__main__':app.run(debug=True)
应用工厂模式
应用工厂模式是一种创建Flask应用实例的设计模式,尤其适用于大型项目。它允许在创建应用实例时动态配置应用,提高了灵活性和可测试性。
实现应用工厂模式:
-
创建工厂函数:
# app/__init__.py from flask import Flask from flask_sqlalchemy import SQLAlchemydb = SQLAlchemy()def create_app(config_filename=None):app = Flask(__name__)if config_filename:app.config.from_pyfile(config_filename)else:app.config.from_object('config.default')db.init_app(app)from .blog.routes import blog_bpapp.register_blueprint(blog_bp)return app
-
运行应用:
# run.py from app import create_appapp = create_app('config/development.py')if __name__ == '__main__':app.run()
模板引擎(Jinja2)
Jinja2简介
Jinja2是Flask默认使用的模板引擎,它允许您在HTML中嵌入Python代码,从而实现动态内容渲染。Jinja2支持模板继承、控制结构、宏等高级功能,使模板编写更加简洁和高效。
模板继承
模板继承是Jinja2的一大特性,允许您定义一个基础模板,并在此基础上创建子模板,避免重复代码。
创建基础模板:
<!-- templates/base.html -->
<!DOCTYPE html>
<html>
<head><title>{% block title %}我的网站{% endblock %}</title><link rel="stylesheet" href="{{ url_for('static', filename='css/styles.css') }}">
</head>
<body><header><h1>我的网站</h1><nav><a href="{{ url_for('home') }}">首页</a> |<a href="{{ url_for('about') }}">关于</a> |<a href="{{ url_for('blog.index') }}">博客</a> |<a href="{{ url_for('contact') }}">联系</a></nav></header><main>{% block content %}{% endblock %}</main><footer><p>© 2025 我的公司</p></footer>
</body>
</html>
创建子模板:
<!-- templates/blog/index.html -->
{% extends 'base.html' %}{% block title %}博客 - 我的网站{% endblock %}{% block content %}<h2>博客文章</h2><ul>{% for post in posts %}<li><a href="{{ url_for('blog.view_post', post_id=post.id) }}">{{ post.title }}</a></li>{% else %}<li>暂无文章。</li>{% endfor %}</ul>
{% endblock %}
控制结构
Jinja2支持多种控制结构,如条件语句和循环,帮助您根据数据动态生成内容。
条件语句示例:
<!-- templates/user_profile.html -->
{% extends 'base.html' %}{% block title %}用户: {{ user.username }}{% endblock %}{% block content %}<h2>用户: {{ user.username }}</h2><p>邮箱: {{ user.email }}</p>{% if user.is_admin %}<p>角色: 管理员</p>{% else %}<p>角色: 普通用户</p>{% endif %}
{% endblock %}
循环示例:
<!-- templates/blog/post_list.html -->
{% extends 'base.html' %}{% block title %}博客文章列表{% endblock %}{% block content %}<h2>博客文章</h2><ul>{% for post in posts %}<li><a href="{{ url_for('blog.view_post', post_id=post.id) }}">{{ post.title }}</a><span> - {{ post.date_posted.strftime('%Y-%m-%d') }}</span></li>{% else %}<li>暂无文章发布。</li>{% endfor %}</ul>
{% endblock %}
宏与自定义过滤器
宏是Jinja2中的一种可重用模板片段,类似于函数。自定义过滤器允许您扩展Jinja2的功能,自定义数据的展示方式。
定义和使用宏:
-
定义宏:
<!-- templates/macros.html --> {% macro render_post(post) %}<div class="post"><h3><a href="{{ url_for('blog.view_post', post_id=post.id) }}">{{ post.title }}</a></h3><p>{{ post.content[:100] }}...</p><p><small>发布于 {{ post.date_posted.strftime('%Y-%m-%d') }}</small></p></div> {% endmacro %}
-
使用宏:
<!-- templates/blog/index.html --> {% extends 'base.html' %} {% import 'macros.html' as macros %}{% block title %}博客 - 我的网站{% endblock %}{% block content %}<h2>博客文章</h2>{% for post in posts %}{{ macros.render_post(post) }}{% else %}<p>暂无文章发布。</p>{% endfor %} {% endblock %}
定义自定义过滤器:
-
创建过滤器:
# app/filters.py from flask import Markupdef nl2br(value):return Markup(value.replace('\n', '<br>'))
-
注册过滤器:
# app/__init__.py from flask import Flask from .filters import nl2brdef create_app(config_filename=None):app = Flask(__name__)# 配置和初始化扩展app.jinja_env.filters['nl2br'] = nl2brreturn app
-
使用过滤器:
<!-- templates/blog/view_post.html --> {% extends 'base.html' %}{% block title %}{{ post.title }}{% endblock %}{% block content %}<h2>{{ post.title }}</h2><p><small>发布于 {{ post.date_posted.strftime('%Y-%m-%d') }}</small></p><div>{{ post.content | nl2br }}</div> {% endblock %}
表单处理
使用Flask-WTF
Flask-WTF是Flask的一个扩展,集成了WTForms,用于简化表单的创建、渲染和验证过程。
安装Flask-WTF:
pip install Flask-WTF
表单验证
Flask-WTF提供了丰富的表单验证功能,确保用户输入的数据符合预期。
创建表单类:
# app/forms.py
from flask_wtf import FlaskForm
from wtforms import StringField, PasswordField, SubmitField, TextAreaField
from wtforms.validators import DataRequired, Email, Length, EqualToclass RegistrationForm(FlaskForm):username = StringField('用户名', validators=[DataRequired(), Length(min=4, max=25)])email = StringField('邮箱', validators=[DataRequired(), Email()])password = PasswordField('密码', validators=[DataRequired(), Length(min=6)])confirm_password = PasswordField('确认密码', validators=[DataRequired(), EqualTo('password')])submit = SubmitField('注册')class LoginForm(FlaskForm):email = StringField('邮箱', validators=[DataRequired(), Email()])password = PasswordField('密码', validators=[DataRequired()])submit = SubmitField('登录')
处理表单数据
在视图函数中处理表单的提交和验证结果。
注册视图函数:
# app/auth/routes.py
from flask import Blueprint, render_template, redirect, url_for, flash
from .forms import RegistrationForm
from app import db
from app.models import Userauth_bp = Blueprint('auth', __name__, url_prefix='/auth')@auth_bp.route('/register', methods=['GET', 'POST'])
def register():form = RegistrationForm()if form.validate_on_submit():user = User(username=form.username.data, email=form.email.data)user.set_password(form.password.data)db.session.add(user)db.session.commit()flash('注册成功!请登录。', 'success')return redirect(url_for('auth.login'))return render_template('auth/register.html', form=form)
模板文件:
<!-- templates/auth/register.html -->
{% extends 'base.html' %}{% block title %}注册{% endblock %}{% block content %}<h2>注册</h2><form method="POST" action="{{ url_for('auth.register') }}">{{ form.hidden_tag() }}<p>{{ form.username.label }}<br>{{ form.username(size=32) }}<br>{% for error in form.username.errors %}<span class="error">{{ error }}</span>{% endfor %}</p><p>{{ form.email.label }}<br>{{ form.email(size=32) }}<br>{% for error in form.email.errors %}<span class="error">{{ error }}</span>{% endfor %}</p><p>{{ form.password.label }}<br>{{ form.password(size=32) }}<br>{% for error in form.password.errors %}<span class="error">{{ error }}</span>{% endfor %}</p><p>{{ form.confirm_password.label }}<br>{{ form.confirm_password(size=32) }}<br>{% for error in form.confirm_password.errors %}<span class="error">{{ error }}</span>{% endfor %}</p><p>{{ form.submit() }}</p></form>
{% endblock %}
数据库集成
使用Flask-SQLAlchemy
Flask-SQLAlchemy是Flask的一个扩展,简化了与数据库的交互。它基于SQLAlchemy ORM,提供了强大的数据库操作能力。
安装Flask-SQLAlchemy:
pip install Flask-SQLAlchemy
配置数据库
在应用配置中设置数据库URI。
# config/development.py
SQLALCHEMY_DATABASE_URI = 'sqlite:///site.db'
SQLALCHEMY_TRACK_MODIFICATIONS = False
SECRET_KEY = 'your_secret_key'
定义模型
使用Flask-SQLAlchemy定义数据库模型。
# app/models.py
from app import db
from werkzeug.security import generate_password_hash, check_password_hash
from flask_login import UserMixinclass User(db.Model, UserMixin):id = db.Column(db.Integer, primary_key=True)username = db.Column(db.String(25), unique=True, nullable=False)email = db.Column(db.String(120), unique=True, nullable=False)password_hash = db.Column(db.String(128), nullable=False)posts = db.relationship('Post', backref='author', lazy=True)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)class Post(db.Model):id = db.Column(db.Integer, primary_key=True)title = db.Column(db.String(100), nullable=False)date_posted = db.Column(db.DateTime, nullable=False, default=db.func.now())content = db.Column(db.Text, nullable=False)user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
数据库迁移
Flask-Migrate基于Alembic,提供数据库迁移的能力,帮助您管理数据库模式的变化。
安装Flask-Migrate:
pip install Flask-Migrate
配置迁移:
# app/__init__.py
from flask_migrate import Migrate
from . import dbdef create_app(config_filename=None):app = Flask(__name__)app.config.from_pyfile(config_filename)db.init_app(app)migrate = Migrate(app, db)# 注册蓝图等return app
初始化迁移环境:
flask db init
创建迁移脚本:
flask db migrate -m "创建用户和博客模型"
应用迁移:
flask db upgrade
关系数据库操作
利用SQLAlchemy ORM进行数据库操作,实现对象与数据库表的映射。
创建新用户和文章:
# 创建新用户
new_user = User(username='张三', email='zhangsan@example.com')
new_user.set_password('securepassword')
db.session.add(new_user)
db.session.commit()# 创建新文章
post = Post(title='第一篇博客', content='这是我的第一篇博客文章。', author=new_user)
db.session.add(post)
db.session.commit()
查询数据:
# 查询所有用户
users = User.query.all()# 查询特定用户
user = User.query.filter_by(username='张三').first()# 查询用户的所有文章
user_posts = user.posts
更新数据:
user.email = 'newemail@example.com'
db.session.commit()
删除数据:
db.session.delete(user)
db.session.commit()
用户认证
使用Flask-Login
Flask-Login是Flask的一个扩展,简化了用户认证和会话管理的过程。
安装Flask-Login:
pip install Flask-Login
配置Flask-Login
初始化Flask-Login:
# app/__init__.py
from flask_login import LoginManagerdef create_app(config_filename=None):app = Flask(__name__)app.config.from_pyfile(config_filename)db.init_app(app)migrate = Migrate(app, db)login_manager = LoginManager()login_manager.login_view = 'auth.login'login_manager.init_app(app)from .models import User@login_manager.user_loaderdef load_user(user_id):return User.query.get(int(user_id))# 注册蓝图等return app
用户注册与登录
注册视图:
已在表单处理部分展示。
登录视图:
# app/auth/routes.py
from flask import Blueprint, render_template, redirect, url_for, flash, request
from flask_login import login_user, logout_user, login_required
from .forms import LoginForm
from app.models import Userauth_bp = Blueprint('auth', __name__, url_prefix='/auth')@auth_bp.route('/login', methods=['GET', 'POST'])
def login():form = LoginForm()if form.validate_on_submit():user = User.query.filter_by(email=form.email.data).first()if user and user.check_password(form.password.data):login_user(user)flash('登录成功!', 'success')next_page = request.args.get('next')return redirect(next_page) if next_page else redirect(url_for('home'))else:flash('登录失败,请检查邮箱和密码。', 'danger')return render_template('auth/login.html', form=form)@auth_bp.route('/logout')
@login_required
def logout():logout_user()flash('已注销登录。', 'info')return redirect(url_for('home'))
登录模板:
<!-- templates/auth/login.html -->
{% extends 'base.html' %}{% block title %}登录{% endblock %}{% block content %}<h2>登录</h2><form method="POST" action="{{ url_for('auth.login') }}">{{ form.hidden_tag() }}<p>{{ form.email.label }}<br>{{ form.email(size=32) }}<br>{% for error in form.email.errors %}<span class="error">{{ error }}</span>{% endfor %}</p><p>{{ form.password.label }}<br>{{ form.password(size=32) }}<br>{% for error in form.password.errors %}<span class="error">{{ error }}</span>{% endfor %}</p><p>{{ form.submit() }}</p></form>
{% endblock %}
权限管理
根据用户的角色或权限控制对特定资源的访问。
定义用户角色:
在用户模型中添加角色字段。
# app/models.py
class User(db.Model, UserMixin):# 其他字段role = db.Column(db.String(20), nullable=False, default='user')def is_admin(self):return self.role == 'admin'
装饰器实现权限控制:
# app/decorators.py
from functools import wraps
from flask import abort
from flask_login import current_userdef admin_required(f):@wraps(f)def decorated_function(*args, **kwargs):if not current_user.is_admin():abort(403)return f(*args, **kwargs)return decorated_function
应用装饰器:
# app/admin/routes.py
from flask import Blueprint, render_template
from flask_login import login_required
from app.decorators import admin_requiredadmin_bp = Blueprint('admin', __name__, url_prefix='/admin')@admin_bp.route('/')
@login_required
@admin_required
def dashboard():return render_template('admin/dashboard.html')
示例项目:博客系统
为了综合应用上述知识,本节将带您构建一个功能完善的博客系统,包含用户注册与登录、博客文章管理及评论功能。
项目结构
flask_blog/
├── app/
│ ├── __init__.py
│ ├── models.py
│ ├── forms.py
│ ├── auth/
│ │ ├── __init__.py
│ │ ├── routes.py
│ │ └── forms.py
│ ├── blog/
│ │ ├── __init__.py
│ │ ├── routes.py
│ │ └── forms.py
│ ├── templates/
│ │ ├── base.html
│ │ ├── auth/
│ │ │ ├── login.html
│ │ │ └── register.html
│ │ ├── blog/
│ │ │ ├── index.html
│ │ │ ├── create_post.html
│ │ │ └── view_post.html
│ │ └── admin/
│ │ └── dashboard.html
│ └── static/
│ └── css/
│ └── styles.css
├── migrations/
├── config/
│ ├── __init__.py
│ ├── default.py
│ └── development.py
├── run.py
└── requirements.txt
实现用户认证
用户注册与登录:
已在用户认证部分展示。
创建和管理博客文章
创建博客文章表单:
# app/blog/forms.py
from flask_wtf import FlaskForm
from wtforms import StringField, TextAreaField, SubmitField
from wtforms.validators import DataRequired, Lengthclass PostForm(FlaskForm):title = StringField('标题', validators=[DataRequired(), Length(min=1, max=100)])content = TextAreaField('内容', validators=[DataRequired()])submit = SubmitField('发布')
博客视图函数:
# app/blog/routes.py
from flask import Blueprint, render_template, redirect, url_for, flash, request
from flask_login import login_required, current_user
from app import db
from app.models import Post
from .forms import PostFormblog_bp = Blueprint('blog', __name__, url_prefix='/blog')@blog_bp.route('/')
def index():posts = Post.query.order_by(Post.date_posted.desc()).all()return render_template('blog/index.html', posts=posts)@blog_bp.route('/create', methods=['GET', 'POST'])
@login_required
def create_post():form = PostForm()if form.validate_on_submit():post = Post(title=form.title.data, content=form.content.data, author=current_user)db.session.add(post)db.session.commit()flash('博客文章发布成功!', 'success')return redirect(url_for('blog.index'))return render_template('blog/create_post.html', form=form)@blog_bp.route('/post/<int:post_id>')
def view_post(post_id):post = Post.query.get_or_404(post_id)return render_template('blog/view_post.html', post=post)
创建博客文章模板:
<!-- templates/blog/create_post.html -->
{% extends 'base.html' %}{% block title %}创建博客文章{% endblock %}{% block content %}<h2>创建博客文章</h2><form method="POST" action="{{ url_for('blog.create_post') }}">{{ form.hidden_tag() }}<p>{{ form.title.label }}<br>{{ form.title(size=64) }}<br>{% for error in form.title.errors %}<span class="error">{{ error }}</span>{% endfor %}</p><p>{{ form.content.label }}<br>{{ form.content(rows=10, cols=70) }}<br>{% for error in form.content.errors %}<span class="error">{{ error }}</span>{% endfor %}</p><p>{{ form.submit() }}</p></form>
{% endblock %}
评论功能
定义评论模型:
# app/models.py
class Comment(db.Model):id = db.Column(db.Integer, primary_key=True)content = db.Column(db.Text, nullable=False)date_posted = db.Column(db.DateTime, nullable=False, default=db.func.now())user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)post_id = db.Column(db.Integer, db.ForeignKey('post.id'), nullable=False)
创建评论表单:
# app/blog/forms.py
class CommentForm(FlaskForm):content = TextAreaField('评论', validators=[DataRequired(), Length(min=1, max=500)])submit = SubmitField('提交评论')
更新视图函数以处理评论:
# app/blog/routes.py
from .forms import PostForm, CommentForm
from app.models import Comment@blog_bp.route('/post/<int:post_id>', methods=['GET', 'POST'])
def view_post(post_id):post = Post.query.get_or_404(post_id)form = CommentForm()if form.validate_on_submit():comment = Comment(content=form.content.data, author=current_user, post=post)db.session.add(comment)db.session.commit()flash('评论提交成功!', 'success')return redirect(url_for('blog.view_post', post_id=post.id))comments = Comment.query.filter_by(post_id=post.id).order_by(Comment.date_posted.asc()).all()return render_template('blog/view_post.html', post=post, form=form, comments=comments)
更新评论模板:
<!-- templates/blog/view_post.html -->
{% extends 'base.html' %}{% block title %}{{ post.title }}{% endblock %}{% block content %}<h2>{{ post.title }}</h2><p><small>发布于 {{ post.date_posted.strftime('%Y-%m-%d') }}</small></p><div>{{ post.content | nl2br }}</div><hr><h3>评论</h3>{% for comment in comments %}<div class="comment"><p>{{ comment.content | nl2br }}</p><p><small>由 {{ comment.author.username }} 于 {{ comment.date_posted.strftime('%Y-%m-%d %H:%M') }}</small></p></div>{% else %}<p>暂无评论。</p>{% endfor %}<hr>{% if current_user.is_authenticated %}<h4>添加评论</h4><form method="POST" action="{{ url_for('blog.view_post', post_id=post.id) }}">{{ form.hidden_tag() }}<p>{{ form.content.label }}<br>{{ form.content(rows=4, cols=70) }}<br>{% for error in form.content.errors %}<span class="error">{{ error }}</span>{% endfor %}</p><p>{{ form.submit() }}</p></form>{% else %}<p><a href="{{ url_for('auth.login') }}">登录</a>后可添加评论。</p>{% endif %}
{% endblock %}
常见问题及解决方法
问题1:如何处理表单的CSRF保护?
原因:跨站请求伪造(CSRF)是一种常见的Web攻击,Flask-WTF通过生成和验证CSRF令牌来防止此类攻击。
解决方法:
-
启用CSRF保护:
在应用配置中设置
SECRET_KEY
,Flask-WTF将自动启用CSRF保护。# config/development.py SECRET_KEY = 'your_secret_key'
-
在表单中包含隐藏的CSRF令牌:
使用
{{ form.hidden_tag() }}
在表单中插入CSRF令牌。<!-- 示例表单 --> <form method="POST" action="{{ url_for('auth.login') }}">{{ form.hidden_tag() }}<!-- 其他表单字段 --> </form>
-
验证CSRF令牌:
Flask-WTF会自动在表单提交时验证CSRF令牌,无需手动处理。
问题2:如何优化数据库查询性能?
原因:在处理大量数据时,未优化的查询可能导致性能瓶颈,影响应用响应速度。
解决方法:
-
使用懒加载和即时加载:
根据需求选择适当的加载策略,避免不必要的数据库查询。
# 使用lazy='joined'进行即时加载 posts = Post.query.options(db.joinedload(Post.author)).all()
-
添加索引:
为频繁查询的字段添加数据库索引,提高查询速度。
# app/models.py class User(db.Model, UserMixin):id = db.Column(db.Integer, primary_key=True)username = db.Column(db.String(25), unique=True, nullable=False, index=True)email = db.Column(db.String(120), unique=True, nullable=False, index=True)# 其他字段
-
分页查询:
对大量数据进行分页展示,减少单次查询的数据量。
# app/blog/routes.py @blog_bp.route('/') def index():page = request.args.get('page', 1, type=int)posts = Post.query.order_by(Post.date_posted.desc()).paginate(page=page, per_page=5)return render_template('blog/index.html', posts=posts)
-
使用原生SQL查询:
在复杂查询场景下,使用原生SQL语句可能比ORM查询更高效。
# 使用db.engine执行原生SQL result = db.engine.execute('SELECT * FROM post WHERE user_id = :user_id', user_id=1) for row in result:print(row)
问题3:如何实现密码的安全存储?
原因:用户密码的安全存储对于保护用户隐私和防止数据泄露至关重要。
解决方法:
-
使用哈希算法:
不要以明文形式存储密码,而应使用强哈希算法进行加密。
from werkzeug.security import generate_password_hash, check_password_hashclass User(db.Model, UserMixin):# 其他字段password_hash = db.Column(db.String(128), nullable=False)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)
-
使用盐(Salt):
哈希算法会自动为密码添加盐,提高安全性,防止彩虹表攻击。
-
定期更新哈希算法:
随着技术的发展,定期评估和更新哈希算法,以应对新的安全威胁。
问题4:如何部署Flask应用到生产环境?
原因:开发环境与生产环境存在差异,直接在生产环境中运行Flask内置服务器不安全且不高效。
解决方法:
-
使用WSGI服务器:
部署Flask应用时,应使用专业的WSGI服务器,如Gunicorn或uWSGI。
# 使用Gunicorn pip install gunicorn gunicorn run:app
-
配置反向代理:
使用Nginx或Apache作为反向代理服务器,处理客户端请求并转发给WSGI服务器。
Nginx示例配置:
server {listen 80;server_name your_domain.com;location / {proxy_pass http://127.0.0.1:8000;proxy_set_header Host $host;proxy_set_header X-Real-IP $remote_addr;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;proxy_set_header X-Forwarded-Proto $scheme;}location /static/ {alias /path/to/your/flask_app/app/static/;} }
-
启用HTTPS:
使用SSL证书为您的网站启用HTTPS,提高数据传输的安全性。可以使用Let’s Encrypt免费获取SSL证书。
-
配置环境变量:
不要将敏感信息(如
SECRET_KEY
、数据库URI)硬编码在代码中,而应通过环境变量配置。export FLASK_ENV=production export SECRET_KEY='your_production_secret_key' export SQLALCHEMY_DATABASE_URI='your_production_db_uri'
-
日志管理:
配置日志记录,监控应用的运行状态和错误信息。
-
使用容器化:
使用Docker等容器技术,简化部署过程,提高环境一致性。
Dockerfile示例:
FROM python:3.9-slimWORKDIR /appCOPY requirements.txt requirements.txt RUN pip install --no-cache-dir -r requirements.txtCOPY . .CMD ["gunicorn", "-w", "4", "-b", "0.0.0.0:8000", "run:app"]
示例项目:博客系统
项目结构
flask_blog/
├── app/
│ ├── __init__.py
│ ├── models.py
│ ├── forms.py
│ ├── auth/
│ │ ├── __init__.py
│ │ ├── routes.py
│ │ └── forms.py
│ ├── blog/
│ │ ├── __init__.py
│ │ ├── routes.py
│ │ └── forms.py
│ ├── templates/
│ │ ├── base.html
│ │ ├── auth/
│ │ │ ├── login.html
│ │ │ └── register.html
│ │ ├── blog/
│ │ │ ├── index.html
│ │ │ ├── create_post.html
│ │ │ └── view_post.html
│ │ └── admin/
│ │ └── dashboard.html
│ └── static/
│ └── css/
│ └── styles.css
├── migrations/
├── config/
│ ├── __init__.py
│ ├── default.py
│ └── development.py
├── run.py
└── requirements.txt
实现用户认证
用户注册与登录:
见前述用户认证部分,确保用户能够注册新账号并登录。
创建和管理博客文章
创建文章视图:
见前述创建博客文章表单和博客视图函数部分。
评论功能
定义评论模型:
见前述评论功能部分,确保用户能够对文章进行评论。
总结
在本篇文章中,我们深入探讨了Flask框架的高级功能,包括扩展的使用、蓝图的组织方式、应用工厂模式的实现、模板引擎Jinja2的高级特性、表单处理、数据库集成以及用户认证。通过详细的代码示例和实战项目——博客系统,您已经掌握了构建功能丰富且结构清晰的Web应用所需的核心技能。
学习建议:
- 构建自己的项目:尝试扩展博客系统,添加更多功能,如标签管理、文章分类、搜索功能等,巩固所学知识。
- 学习更多Flask扩展:探索如Flask-Admin、Flask-Mail、Flask-RESTful等扩展,提升应用的功能和用户体验。
- 优化应用性能:研究Flask应用的性能优化技巧,如缓存策略、数据库优化、异步任务处理等。
- 安全性提升:深入了解Web应用的安全性,学习防范常见的安全漏洞,如SQL注入、XSS攻击等。
- 部署与运维:学习如何将Flask应用部署到不同的平台,并掌握基本的运维技能,确保应用的稳定运行。
- 参与开源社区:通过参与Flask相关的开源项目,学习业界最佳实践,提升编程和协作能力。
- 持续学习:关注Flask和Web开发的最新动态,阅读官方文档和相关书籍,如《Flask Web Development》以保持知识的更新。
如果您有任何问题或需要进一步的帮助,请随时在评论区留言或联系相关技术社区。
相关文章:

第19篇:python高级编程进阶:使用Flask进行Web开发
第19篇:python高级编程进阶:使用Flask进行Web开发 内容简介 在第18篇文章中,我们介绍了Web开发的基础知识,并使用Flask框架构建了一个简单的Web应用。本篇文章将深入探讨Flask的高级功能,涵盖模板引擎(Ji…...

js截取video视频某一帧为图片
1.代码如下 <template><div class"box"><div class"video-box"><video controls ref"videoRef" preload"true"src"https://qt-minio.ictshop.com.cn:9000/resource-management/2025/01/08/7b96ac9d957c45a…...

[云讷科技]Kerloud Falcon四旋翼飞车虚拟仿真空间发布
虚拟仿真环境作为一个独立的专有软件包提供给我们的客户,用于帮助用户在实际测试之前验证自身的代码,并通过在仿真引擎中添加新的场景来探索新的飞行驾驶功能。 环境要求 由于环境依赖关系,虚拟仿真只能运行在装有Ubuntu 18.04的Intel-64位…...

Jetson nano 安装 PCL 指南
本指南帮助 ARM64 架构的 Jetson Nano 安装 PCL(点云库)。 安装步骤 第一步:安装依赖 在终端中运行以下命令,安装 PCL 所需的依赖: sudo apt-get update sudo apt-get install git build-essential linux-libc-dev s…...

go-zero框架基本配置和错误码封装
文章目录 加载配置信息配置 env加载.env文件配置servicecontext 查询数据生成model文件执行查询操作 错误码封装配置拦截器错误码封装 接上一篇:《go-zero框架快速入门》 加载配置信息 配置 env 在项目根目录下新增 .env 文件,可以配置当前读取哪个环…...

Android中Service在新进程中的启动流程2
目录 1、Service在客户端的启动入口 2、Service启动在AMS的处理 3、Service在新进程中的启动 4、Service与AMS的关系再续 上一篇文章中我们了解了Service在新进程中启动的大致流程,同时认识了与客户端进程交互的接口IApplicationThread以及与AMS交互的接口IActi…...

论文速读|Matrix-SSL:Matrix Information Theory for Self-Supervised Learning.ICML24
论文地址:Matrix Information Theory for Self-Supervised Learning 代码地址:https://github.com/yifanzhang-pro/matrix-ssl bib引用: article{zhang2023matrix,title{Matrix Information Theory for Self-Supervised Learning},author{Zh…...

ubunut22.04安装docker(基于阿里云 Docker 镜像源安装 Docker)
安装 更新包管理器: sudo apt update 安装 Docker 的依赖包 sudo apt install apt-transport-https ca-certificates curl gnupg lsb-release添加阿里云 Docker 镜像源 GPG 密钥: curl -fsSL https://mirrors.aliyun.com/docker-ce/linux/ubuntu/gp…...

k8s namespace绑定节点
k8s namespace绑定节点 1. apiserver 启用准入控制 PodNodeSelector2. namespace 添加注解 scheduler.alpha.kubernetes.io/node-selector3. label node 1. apiserver 启用准入控制 PodNodeSelector vim /etc/kubernetes/manifests/kube-apiserver.yaml spec:containers:- co…...

【ElementPlus】在Vue3中实现表格组件封装
预览 搜索筛选组件 <template><div><el-formref"formView":model"formData"label-width"auto"label-position"right":label-col-style"{ min-width: 100px }":inline"true"><el-form-item …...

cursor重构谷粒商城04——vagrant技术快速部署虚拟机
前言:这个系列将使用最前沿的cursor作为辅助编程工具,来快速开发一些基础的编程项目。目的是为了在真实项目中,帮助初级程序员快速进阶,以最快的速度,效率,快速进阶到中高阶程序员。 本项目将基于谷粒商城…...

26、正则表达式
目录 一. 匹配字符 .:匹配除换行符外的任意单个字符。 二. 位置锚点 ^:匹配输入字符串的开始位置。 $:匹配输入字符串的结束位置。 \b:匹配单词边界。 \B:匹配非单词边界。 三. 重复限定符 *:匹配…...

SpringBoot使用MockMVC通过http请求controller控制器调用测试
说明 在Spring Boot中编写测试控制器调用是一个常见的需求,通常使用Spring的测试框架来完成。Spring Boot提供了多种方式来测试控制器,包括使用MockMvc进行模拟HTTP请求和响应的测试。 基本示例 1. 创建Spring Boot项目 首先,确保你已经创建了一个Spring Boot项目。如果…...

【Unity3D】Unity混淆工具Obfuscator使用
目录 一、导入工具 二、各种混淆形式介绍 2.1 程序集混淆 2.2 命名空间混淆 2.3 类混淆 2.4 函数混淆 2.5 参数混淆 2.6 字段混淆 2.7 属性混淆 2.8 事件混淆 三、安全混淆 四、兼容性处理 4.1 动画方法兼容 4.2 GUI方法兼容 4.3 协程方法兼容 五、选项 5.1 调…...

C语言语法基础学习—动态分配空间(new和malloc的用法及区别)
前言 在 C 语言中,动态内存分配主要是通过 malloc() 和 free() 函数来完成的。而在 C 中是使用new和delete关键字,来动态分配内存。 虽然 C 语言没有 new,但 malloc() 和 new 在内存分配上的作用是相似的。下面我们详细解释 malloc() 和 ne…...

QT:控件属性及常用控件(3)-----输入类控件(正则表达式)
输入类控件既可以进行显示,也能让用户输入一些内容! 文章目录 1.Line Edit1.1 用户输入个人信息1.2 基于正则表达式的文本限制1.3 验证两次输入的密码是否一致1.4 让输入的密码可以被查看 2.Text Edit2.1 输入和显示同步2.1 其他信号出发情况 3.ComboBox…...

Hive SQL 执行计划解析
Hive SQL 执行计划解析 一、 explain用法 1. SQL 查询 EXPLAIN SELECT SUM(view_dsp) AS view_sum FROM ads.table_a WHERE p_day 2025-01-06;2. 执行计划 STAGE DEPENDENCIES:Stage-1 is a root stageStage-0 depends on stages: Stage-1STAGE PLANS:Stage: Stage-1Map …...

热更新杂乱记
热更新主要有一个文件的MD5值的比对过程,期间遇到2个问题,解决起来花费了一点时间 1. png 和 plist 生成zip的时候再生成MD5值会发生变动。 这个问题解决起来有2种方案: (1).第一个方案是将 png和plist的文件时间改…...

博客搭建 — GitHub Pages 部署
关于 GitHub Pages GitHub Pages 是一项静态站点托管服务,它直接从 GitHub 上的仓库获取 HTML、CSS 和 JavaScript 文件,通过构建过程运行文件,然后发布网站。 本文最终效果是搭建出一个域名为 https://<user>.github.io 的网站 创建…...

翻译:How do I reset my FPGA?
文章目录 背景翻译:How do I reset my FPGA?1、Understanding the flip-flop reset behavior2、Reset methodology3、Use appropriate resets to maximize utilization4、Many options5、About the author 背景 在写博客《复位信号的同步与释放(同步复…...

Linux 进程环境变量:深入理解与实践指南
🌟 快来参与讨论💬,点赞👍、收藏⭐、分享📤,共创活力社区。🌟 🚩用通俗易懂且不失专业性的文字,讲解计算机领域那些看似枯燥的知识点🚩 在 Linux 系统里…...

Linux探秘坊-------5.git
1.git介绍 1.版本控制器 为了能够更⽅便我们管理这些不同版本的⽂件,便有了版本控制器。所谓的版本控制器,就是能让你了解到⼀个⽂件的历史,以及它的发展过程的系统。通俗的讲就是⼀个可以记录⼯程的每⼀次改动和版本迭代的⼀个管理系统&am…...

Linux中的几个基本指令(二)
文章目录 1、cp指令例一:例二:例三:例四:例五: 2、mv 指令例一:例二: 3、cat指令例一: 4、tac指令5、which指令6、date指令时间戳:7、zip指令 今天我们继续学习Linux下的…...

Java入门笔记(1)
引言 在计算机编程的广袤宇宙中,Java无疑是一颗格外耀眼的恒星。那么,Java究竟是什么呢? Java是美国Sun公司(Stanford University Network)在1995年推出的一门计算机高级编程语言。曾经辉煌的Sun公司在2009年被Oracle&…...

设计模式的艺术-开闭原则
原则使用频率图(仅供参考) 1.如何理解开闭原则 简单来说,开闭原则指的是 “对扩展开放,对修改关闭”。 当软件系统需要增加新的功能时,应该通过扩展现有代码的方式来实现,而不是去修改已有的代码。 例如我…...

【C语言系列】深入理解指针(3)
深入理解指针(3) 一、字符指针变量二、数组指针变量2.1数组指针变量是什么?2.2数组指针变量怎么初始化? 三、二维数组传参的本质四、函数指针变量4.1函数指针变量的创建4.2函数指针变量的使用4.3两段有趣的代码4.4 typedef关键字 …...

three.js+WebGL踩坑经验合集:写在前面的话
笔者从2023年初开始参与一个基于three.js引擎的web项目的开发工作。本打算2024年春节就把期间踩过的坑写到博客上分享给大家,然而哪怕本专栏的各种构思和内容已经在笔者的脑海里翻滚了一年,得了严重拖延症患者的我还是一直拖到了现在,实在惭愧…...

利用Linux的工作队列(Workqueue)实现中断下半部的处理
本文代码在哪个基础上修改而成? 本文是在博文 https://blog.csdn.net/wenhao_ir/article/details/145228617 的代码基础上修改而成。 关于工作队列(Workqueue)的概念 工作队列(Workqueue)可以用于实现Linux的中断下半部的,之前在博文 https://blog.cs…...

LabVIEW处理复杂系统和数据处理
LabVIEW 是一个图形化编程平台,广泛应用于自动化控制、数据采集、信号处理、仪器控制等复杂系统的开发。它的图形化界面使得开发人员能够直观地设计系统和算法,尤其适合处理需要实时数据分析、高精度控制和复杂硬件集成的应用场景。LabVIEW 提供丰富的库…...

spring-springboot -springcloud
目录 spring: 动态代理: spring的生命周期(bean的生命周期): SpringMvc的生命周期: SpringBoot: 自动装配: 自动装配流程: Spring中常用的注解: Spring Boot中常用的注解: SpringCloud: 1. 注册中心: 2. gateway(网关): 3. Ribbon(负载均…...