项目介绍与规划

在本章中,我们将带领大家创建一个简单但功能齐全的 Web 应用,通过实践来巩固前面的学习内容。我们将使用 Flask 框架,逐步实现用户注册与登录功能,以及数据展示与交互功能。最后,我们讨论如何将应用部署到云平台。

项目需求分析与功能规划

在开始编码之前,我们需要对项目进行需求分析和功能规划。以下是我们将实现的主要功能:

  1. 用户注册与登录
    • 用户可以注册新账户
    • 用户可以使用已注册账户登录
  2. 数据展示与交互
    • 登录成功后,用户可以看到一个欢迎页面
    • 用户可以查看和更新个人信息

项目目录结构的设计

为了保持代码的整洁和组织有序,我们将采用如下的目录结构:

  1. flask_app/
  2. ├── app/
  3. ├── static/
  4. ├── templates/
  5. ├── __init__.py
  6. ├── routes.py
  7. └── models.py
  8. ├── venv/
  9. ├── config.py
  10. ├── run.py
  11. ├── requirements.txt
  12. └── README.md

开发与实现

使用 Flask 创建 Web 应用

首先,我们需要创建一个虚拟环境并安装 Flask:

  1. # 创建虚拟环境
  2. python3 -m venv venv
  3. # 激活虚拟环境(Unix 或 macOS)
  4. source venv/bin/activate
  5. # 激活虚拟环境(Windows)
  6. venv\Scripts\activate
  7. # 安装 Flask
  8. pip install Flask

项目初始化

flask_app 目录下创建 run.py 文件,并编写如下代码:

  1. from app import create_app
  2. app = create_app()
  3. if __name__ == '__main__':
  4. app.run(debug=True)

接着,在 app 目录下创建 __init__.py 文件,并编写如下代码:

  1. from flask import Flask
  2. def create_app():
  3. app = Flask(__name__)
  4. app.config['SECRET_KEY'] = 'your_secret_key'
  5. from .routes import main
  6. app.register_blueprint(main)
  7. return app

实现用户注册与登录功能

创建数据库模型

app 目录下创建 models.py 文件,并编写如下代码:

  1. from flask_sqlalchemy import SQLAlchemy
  2. db = SQLAlchemy()
  3. class User(db.Model):
  4. id = db.Column(db.Integer, primary_key=True)
  5. username = db.Column(db.String(150), unique=True, nullable=False)
  6. password = db.Column(db.String(150), nullable=False)

创建注册与登录路由

app 目录下创建 routes.py 文件,并编写如下代码:

  1. from flask import Blueprint, render_template, redirect, url_for, request, flash
  2. from .models import User, db
  3. from werkzeug.security import generate_password_hash, check_password_hash
  4. main = Blueprint('main', __name__)
  5. @main.route('/')
  6. def index():
  7. return render_template('index.html')
  8. @main.route('/signup', methods=['GET', 'POST'])
  9. def signup():
  10. if request.method == 'POST':
  11. username = request.form.get('username')
  12. password = request.form.get('password')
  13. user = User.query.filter_by(username=username).first()
  14. if user:
  15. flash('Username already exists')
  16. return redirect(url_for('main.signup'))
  17. new_user = User(username=username, password=generate_password_hash(password, method='sha256'))
  18. db.session.add(new_user)
  19. db.session.commit()
  20. return redirect(url_for('main.login'))
  21. return render_template('signup.html')
  22. @main.route('/login', methods=['GET', 'POST'])
  23. def login():
  24. if request.method == 'POST':
  25. username = request.form.get('username')
  26. password = request.form.get('password')
  27. user = User.query.filter_by(username=username).first()
  28. if not user or not check_password_hash(user.password, password):
  29. flash('Invalid username or password')
  30. return redirect(url_for('main.login'))
  31. return redirect(url_for('main.profile'))
  32. return render_template('login.html')
  33. @main.route('/profile')
  34. def profile():
  35. return render_template('profile.html')

创建模板文件

app/templates 目录下创建以下 HTML 文件:

index.html

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <title>Home</title>
  5. </head>
  6. <body>
  7. <h1>Welcome to the Flask Web App!</h1>
  8. <a href="{{ url_for('main.signup') }}">Sign Up</a>
  9. <a href="{{ url_for('main.login') }}">Log In</a>
  10. </body>
  11. </html>

signup.html

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <title>Sign Up</title>
  5. </head>
  6. <body>
  7. <h1>Sign Up</h1>
  8. <form method="POST">
  9. <label>Username:</label>
  10. <input type="text" name="username" required />
  11. <label>Password:</label>
  12. <input type="password" name="password" required />
  13. <button type="submit">Sign Up</button>
  14. </form>
  15. <a href="{{ url_for('main.login') }}">Log In</a>
  16. </body>
  17. </html>

login.html

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <title>Log In</title>
  5. </head>
  6. <body>
  7. <h1>Log In</h1>
  8. <form method="POST">
  9. <label>Username:</label>
  10. <input type="text" name="username" required />
  11. <label>Password:</label>
  12. <input type="password" name="password" required />
  13. <button type="submit">Log In</button>
  14. </form>
  15. <a href="{{ url_for('main.signup') }}">Sign Up</a>
  16. </body>
  17. </html>

profile.html

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <title>Profile</title>
  5. </head>
  6. <body>
  7. <h1>Welcome to your profile page!</h1>
  8. <a href="{{ url_for('main.index') }}">Home</a>
  9. </body>
  10. </html>

实现数据展示与交互功能

更新用户信息

routes.py 文件中,添加如下路由:

  1. @main.route('/update_profile', methods=['GET', 'POST'])
  2. def update_profile():
  3. if request.method == 'POST':
  4. username = request.form.get('username')
  5. user = User.query.filter_by(username=username).first()
  6. if user:
  7. user.username = request.form.get('new_username')
  8. db.session.commit()
  9. flash('Profile updated successfully')
  10. else:
  11. flash('User not found')
  12. return redirect(url_for('main.profile'))
  13. return render_template('update_profile.html')

创建更新用户信息模板

app/templates 目录下创建 update_profile.html 文件,并编写如下代码:

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <title>Update Profile</title>
  5. </head>
  6. <body>
  7. <h1>Update Profile</h1>
  8. <form method="POST">
  9. <label>Current Username:</label>
  10. <input type="text" name="username" required />
  11. <label>New Username:</label>
  12. <input type="text" name="new_username" required />
  13. <button type="submit">Update</button>
  14. </form>
  15. <a href="{{ url_for('main.profile') }}">Profile</a>
  16. </body>
  17. </html>

部署与发布

部署到 Heroku

  1. 创建 Procfile 文件并添加以下内容:
  1. web: gunicorn run:app
  1. 创建 requirements.txt 文件:
  1. pip freeze > requirements.txt
  1. 将项目推送到 GitHub 仓库:
  1. git init
  2. git add .
  3. git commit -m "Initial commit"
  4. git remote add origin <your_repository_url>
  5. git push -u origin master
  1. 在 Heroku 创建一个新的应用并部署:
  1. heroku create <your_app_name>
  2. git push heroku master

使用 Docker 进行容器化部署

  1. 创建 Dockerfile 文件并添加以下内容:
  1. FROM python:3.8-slim
  2. WORKDIR /app
  3. COPY requirements.txt requirements.txt
  4. RUN pip install -r requirements.txt
  5. COPY . .
  6. CMD ["gunicorn", "-b", "0.0.0.0:8000", "run:app"]
  1. 构建 Docker 镜像并运行容器:
  1. docker build -t flask_app .
  2. docker run -d -p 8000:8000 flask_app
  1. 验证应用在 Docker 容器中运行:
    打开浏览器,访问 http://localhost:8000,确保应用正常运行。

实现数据展示与交互功能

更新用户信息

routes.py 文件中,添加如下路由:

  1. @main.route('/update_profile', methods=['GET', 'POST'])
  2. def update_profile():
  3. if request.method == 'POST':
  4. username = request.form.get('username')
  5. user = User.query.filter_by(username=username).first()
  6. if user:
  7. user.username = request.form.get('new_username')
  8. db.session.commit()
  9. flash('Profile updated successfully')
  10. else:
  11. flash('User not found')
  12. return redirect(url_for('main.profile'))
  13. return render_template('update_profile.html')

创建更新用户信息模板

app/templates 目录下创建 update_profile.html 文件,并编写如下代码:

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <title>Update Profile</title>
  5. </head>
  6. <body>
  7. <h1>Update Profile</h1>
  8. <form method="POST">
  9. <label>Current Username:</label>
  10. <input type="text" name="username" required />
  11. <label>New Username:</label>
  12. <input type="text" name="new_username" required />
  13. <button type="submit">Update</button>
  14. </form>
  15. <a href="{{ url_for('main.profile') }}">Profile</a>
  16. </body>
  17. </html>

结论

通过本章的项目实战,我们成功创建了一个功能齐全的 Web 应用,并通过 Flask 框架实现了用户注册与登录功能,以及数据展示与交互功能。我们还学习了如何将应用部署到 Heroku 和使用 Docker 进行容器化部署。这些实践不仅巩固了我们对 Python 基础和进阶知识的理解,也为我们提供了一个完整的 Web 开发工作流示例,帮助我们更好地理解实际开发中的各个环节。