在Flask框架的学习旅程中,通过实际项目来巩固知识是不可或缺的一环。本章节将带领你构建一个完整的在线投票系统,该系统允许用户创建投票、参与投票并查看投票结果。通过这个项目,你将深入理解Flask的路由、模板渲染、表单处理、数据库操作(使用SQLite为例)、会话管理以及用户认证等核心概念。
在线投票系统主要由以下几个模块组成:
在开始编码之前,请确保你的开发环境已经安装了Python和Flask。此外,还需要安装Flask-SQLAlchemy(用于数据库操作)、Flask-Login(用于用户认证)和Flask-WTF(用于表单处理)等扩展库。可以通过pip安装这些库:
pip install Flask Flask-SQLAlchemy Flask-Login Flask-WTF
首先,设计数据库模型。我们需要至少三个表:User
(用户)、Vote
(投票)和Choice
(投票选项)。
from flask_sqlalchemy import SQLAlchemy
from flask_login import UserMixin
from datetime import datetime
db = SQLAlchemy()
class User(db.Model, UserMixin):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(64), unique=True, nullable=False)
email = db.Column(db.String(120), unique=True, nullable=False)
password_hash = db.Column(db.String(128), nullable=False)
def __repr__(self):
return f'<User {self.username}>'
class Vote(db.Model):
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(255), nullable=False)
start_time = db.Column(db.DateTime, default=datetime.utcnow)
end_time = db.Column(db.DateTime, nullable=True)
active = db.Column(db.Boolean, default=True)
choices = db.relationship('Choice', backref='vote', lazy=True)
def __repr__(self):
return f'<Vote {self.title}>'
class Choice(db.Model):
id = db.Column(db.Integer, primary_key=True)
vote_id = db.Column(db.Integer, db.ForeignKey('vote.id'), nullable=False)
choice_text = db.Column(db.String(255), nullable=False)
votes = db.Column(db.Integer, default=0)
def __repr__(self):
return f'<Choice {self.choice_text}>'
使用Flask-Login来处理用户认证。首先,配置Flask-Login并创建用户加载器函数:
from flask_login import LoginManager, login_user, logout_user, login_required, current_user
login_manager = LoginManager()
login_manager.login_view = 'auth.login'
login_manager.init_app(app)
@login_manager.user_loader
def load_user(user_id):
return User.query.get(int(user_id))
# 示例登录函数
@app.route('/login', methods=['GET', 'POST'])
def login():
# 省略表单处理和验证逻辑
user = User.query.filter_by(username=form.username.data).first()
if user is None or not check_password_hash(user.password_hash, form.password.data):
flash('Invalid username or password')
return redirect(url_for('login'))
login_user(user, remember=form.remember_me.data)
return redirect(url_for('main.index'))
创建投票:
from flask import Blueprint, render_template, request, redirect, url_for, flash
from .forms import VoteForm
vote_bp = Blueprint('vote', __name__)
@vote_bp.route('/create', methods=['GET', 'POST'])
@login_required
def create_vote():
form = VoteForm()
if form.validate_on_submit():
vote = Vote(title=form.title.data, start_time=datetime.utcnow())
db.session.add(vote)
db.session.commit()
for choice in form.choices.data:
new_choice = Choice(vote_id=vote.id, choice_text=choice)
db.session.add(new_choice)
db.session.commit()
flash('Vote created successfully!')
return redirect(url_for('vote.view_vote', vote_id=vote.id))
return render_template('create_vote.html', form=form)
参与投票:
@vote_bp.route('/<int:vote_id>/vote', methods=['GET', 'POST'])
@login_required
def vote_on_vote(vote_id):
vote = Vote.query.get_or_404(vote_id)
if not vote.active:
flash('This vote is not active.')
return redirect(url_for('vote.view_vote', vote_id=vote_id))
# 假设我们使用简单的单选逻辑
choice_id = request.form.get('choice')
if choice_id:
choice = Choice.query.get(choice_id)
if choice and current_user.id not in [v.user_id for v in choice.votes]:
choice.votes += 1
# 这里可以添加额外的逻辑来记录投票用户
db.session.commit()
flash('Your vote has been cast!')
else:
flash('You have already voted for this option or you are not allowed to vote again.')
return redirect(url_for('vote.view_vote', vote_id=vote_id))
# 省略view_vote等函数实现,以展示投票结果
flash
消息和适当的HTTP状态码来通知用户操作结果。通过开发这个在线投票系统,你不仅掌握了Flask框架的基本用法,还深入理解了Web应用开发中常见的模式和挑战,如用户认证、表单处理、数据库操作及安全性考虑。这个项目可以作为你进一步学习Flask和Web开发的坚实基础,激发你探索更多高级特性和最佳实践的兴趣。