第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…...
深度学习框架应用开发:基于 TensorFlow 的函数求导分析
深度学习框架应用开发:基于 TensorFlow 的函数求导分析 在深度学习的世界里,梯度计算是优化算法的核心。而 TensorFlow 作为一款强大的深度学习框架,为我们提供了简洁而强大的工具来进行自动求导操作,这极大地简化了深度学习模型的…...
【学术会议征稿-第二届生成式人工智能与信息安全学术会议(GAIIS 2025)】人工智能与信息安全的魅力
重要信息 时间:2025年2月21日-23日 地点:中国杭州 官网:http://www.ic-gaiis.org 简介 2025年第二届生成式人工智能与信息安全将于 2025年2月21日-23日在中国杭州举行。主要围绕“生成式人工智能与信息安全”的最新研究展开,…...
2025春晚刘谦魔术揭秘魔术过程
2025春晚刘谦魔术揭秘魔术过程 首先来看全过程 将杯子,筷子,勺子以任意顺序摆成一排 1.筷子和左边物体交换位置 2.杯子和右边物体交换位置 3.勺子和左边物体交换位置 最终魔术的结果是右手出现了杯子 这个就是一个简单的分类讨论的问题。 今年的魔术…...
postgresql的用户、数据库和表
在 PostgreSQL 中,用户、数据库和表是关系型数据库系统的基本组成部分。理解这些概念对数据库管理和操作至关重要。下面是对这些概念的详细解释: 1. 用户(User) 在 PostgreSQL 中,用户(也称为 角色&#…...
上海亚商投顾:沪指冲高回落 大金融板块全天强势 上海亚商投
上海亚商投顾前言:无惧大盘涨跌,解密龙虎榜资金,跟踪一线游资和机构资金动向,识别短期热点和强势个股。 一.市场情绪 市场全天冲高回落,深成指、创业板指午后翻绿。大金融板块全天强势,天茂集团…...
06-机器学习-数据预处理
数据清洗 数据清洗是数据预处理的核心步骤,旨在修正或移除数据集中的错误、不完整、重复或不一致的部分,为后续分析和建模提供可靠基础。以下是数据清洗的详细流程、方法和实战示例: 一、数据清洗的核心任务 问题类型表现示例影响缺失值数值…...
01学习预热篇(D6_正式踏入JVM深入学习前的铺垫)
目录 学习前言 一、虚拟机的结构 1. Java虚拟机参数设置 2. java 堆 3. 出入栈 4. 局部变量表 1> 局部变量的剖析 2> 局部变量的回收 5. 操作数栈 1> 常量入栈指令 2> 局部变量值转载到栈中指令 3> 将栈顶值保存到局部变量中指令 6. 帧数据区 7. 栈…...
【漫话机器学习系列】068.网格搜索(GridSearch)
网格搜索(Grid Search) 网格搜索(Grid Search)是一种用于优化机器学习模型超参数的技术。它通过系统地遍历给定的参数组合,找出使模型性能达到最优的参数配置。 网格搜索的核心思想 定义参数网格 创建一个包含超参数值…...
https数字签名手动验签
以bing.com 为例 1. CA 层级的基本概念 CA 层级是一种树状结构,由多个层级的 CA 组成。每个 CA 负责为其下一层级的实体(如子 CA 或终端实体)颁发证书。层级结构的顶端是 根 CA(Root CA),它是整个 PKI 体…...
【股票数据API接口36】如何获取股票当天逐笔大单交易数据之Python、Java等多种主流语言实例代码演示通过股票数据接口获取数据
如今,量化分析在股市领域风靡一时,其核心要素在于数据,获取股票数据,是踏上量化分析之路的第一步。你可以选择亲手编写爬虫来抓取,但更便捷的方式,莫过于利用专业的股票数据API接口。自编爬虫虽零成本&a…...
RocketMQ 中如何实现消息的可靠传递?
引言 作为头部消息队列开源中间件,学习其中的技术方案并且总结可靠性和健壮性,提升我们的架构思维和解决问题的能力 。 在 RocketMQ 中实现消息的可靠传递可以从多个方面入手,涵盖生产者、Broker 以及消费者等不同环节。 生产者端 1. 同步…...
Elasticsearch+kibana安装(简单易上手)
下载ES( Download Elasticsearch | Elastic ) 将ES安装包解压缩 解压后目录如下: 修改ES服务端口(可以不修改) 启动ES 记住这些内容 验证ES是否启动成功 下载kibana( Download Kibana Free | Get Started Now | Elastic ) 解压后的kibana目…...
视频多模态模型——视频版ViT
大家好,这里是好评笔记,公主号:Goodnote,专栏文章私信限时Free。本文详细解读多模态论文《ViViT: A Video Vision Transformer》,2021由google 提出用于视频处理的视觉 Transformer 模型,在视频多模态领域有…...
单机伪分布Hadoop详细配置
目录 1. 引言2. 配置单机Hadoop2.1 下载并解压JDK1.8、Hadoop3.3.62.2 配置环境变量2.3 验证JDK、Hadoop配置 3. 伪分布Hadoop3.1 配置ssh免密码登录3.2 配置伪分布Hadoop3.2.1 修改hadoop-env.sh3.2.2 修改core-site.xml3.2.3 修改hdfs-site.xml3.2.4 修改yarn-site.xml3.2.5 …...
Ollama windows安装
Ollama 是一个开源项目,专注于帮助用户本地化运行大型语言模型(LLMs)。它提供了一个简单易用的框架,让开发者和个人用户能够在自己的设备上部署和运行 LLMs,而无需依赖云服务或外部 API。这对于需要数据隐私、离线使用…...
鸿蒙next 自定义日历组件
效果图预览 20250124-113957 使用说明 1.选择日期左右箭头,实现每月日历切换,示例中超出当前月份,禁止进入下一月,可在代码更改 2.日历中显示当前选择的日期,选中的日期颜色可自定义 3.日历中可展示历史记录作为数据…...
Nginx 开发总结
文章目录 1. Nginx 基础概念1-1、什么是 Nginx1-2、Nginx 的工作原理1-3、Nginx 的核心特点1-4、Nginx 的常见应用场景1-5、Nginx 与 Apache 的区别1-6、 Nginx 配置的基本结构1-7、Nginx 常见指令 2. Nginx 配置基础2-1、Nginx 配置文件结构2-2、全局配置 (Global Block)2-3、…...
Van-Nav:新年,将自己学习的项目地址统一整理搭建自己的私人导航站,供自己后续查阅使用,做技术的同学应该都有一个自己网站的梦想
嗨,大家好,我是小华同学,关注我们获得“最新、最全、最优质”开源项目和高效工作学习方法 Van-Nav是一个基于Vue.js开发的导航组件库,它提供了多种预设的样式和灵活的配置选项,使得开发者可以轻松地定制出符合项目需求…...
层次聚类构建层次结构的簇
层次聚类(Hierarchical Clustering)可以通过自定义函数来完成。层次聚类可以分为两种方法:凝聚型(Agglomerative)和分裂型(Divisive)。这里主要介绍一种常用的凝聚型方法,它是自底向…...
计算机网络__基础知识问答
Question: 1)在计算机网络的5层结构中,每一层的功能大概是什么? 2)交换机的功能?https://www.bilibili.com/video/BV1na4y1L7Ev 3)路由器的功能?https://www.bilibili.com/video/BV1hv411k7n…...
网易云音乐歌名可视化:词云生成与GitHub-Pages部署实践
引言 本文将基于前一篇爬取的网易云音乐数据, 利用Python的wordcloud、matplotlib等库, 对歌名数据进行深入的词云可视化分析. 我们将探索不同random_state对词云布局的影响, 并详细介绍如何将生成的词云图部署到GitHub Pages, 实现数据可视化的在线展示. 介绍了如何从原始数据…...
PHP根据IP地址获取地理位置城市和经纬度信息
/** 根据IP地址 获取地理位置*/ function getLocationByIP($ip) {$url "http://ip-api.com/json/{$ip}?langzh-CN&fieldsstatus,message,country,countryCode,region,regionName,city,lat,lon,timezone,isp,org,as";$response file_get_contents($url);$data …...
渲染流程概述
渲染流程包括 CPU应用程序端渲染逻辑 和 GPU渲染管线 一、CPU应用程序端渲染逻辑 剔除操作对物体进行渲染排序打包数据调用Shader SetPassCall 和 Drawcall 1.剔除操作 视椎体剔除 (给物体一个包围盒,利用包围盒和摄像机的视椎体进行碰撞检测…...
【单细胞-第三节 多样本数据分析】
文件在单细胞\5_GC_py\1_single_cell\1.GSE183904.Rmd GSE183904 数据原文 1.获取临床信息 筛选样本可以参考临床信息 rm(list ls()) library(tinyarray) a geo_download("GSE183904")$pd head(a) table(a$Characteristics_ch1) #统计各样本有多少2.批量读取 学…...
libOnvif通过组播不能发现相机
使用libOnvif库OnvifDiscoveryClient类, auto discovery new OnvifDiscoveryClient(QUrl(“soap.udp://239.255.255.250:3702”), cb.Build()); 会有错误: end of file or no input: message transfer interrupted or timed out(30 sec max recv delay)…...
项目集成GateWay
文章目录 1.环境搭建1.创建sunrays-common-cloud-gateway-starter模块2.目录结构3.自动配置1.GateWayAutoConfiguration.java2.spring.factories 3.pom.xml4.注意:GateWay不能跟Web一起引入! 1.环境搭建 1.创建sunrays-common-cloud-gateway-starter模块…...
2025年01月28日Github流行趋势
项目名称:maybe 项目地址url:https://github.com/maybe-finance/maybe项目语言:Ruby历史star数:37540今日star数:1004项目维护者:zachgoll, apps/dependabot, tmyracle, Shpigford, crnsh项目简介ÿ…...
使用Ollama本地部署DeepSeek R1
前言 DeepSeek是一款开源的智能搜索引擎,能够通过深度学习技术提高搜索的智能化水平。如果你正在寻找一种方式来将DeepSeek部署在本地环境中,Ollama是一个非常方便的工具,它允许你在本地快速部署并管理各种基于AI的模型。 在本篇博客中&…...
doris:异常数据处理
在导入过程中,源数据列与目标列的数据类型可能存在不一致的情况。导入过程会对这些类型不一致的数据进行转换,但在转换过程中可能会出现字段类型不匹配、字段超长、精度不匹配等问题,从而导致转换失败。 为了处理这些异常情况,Do…...
