Python 项目实战: 基于 Flask 的在线商城开发
Python 是一门优秀的编程语言,在 Web 开发领域中也应用广泛。其中,Flask 是一个简单而灵活的 Python Web 框架,可以帮助开发者快速地构建 Web 应用程序。本篇文章将介绍如何使用 Flask 构建一个简单的在线商城,主要包括以下几个方面内容。
### 项目概述
我们将基于 Flask 构建一个在线商城,包含商品展示、购买、支付等基本功能。
对于该项目,我们需要掌握以下技术知识:
- Flask Web 开发框架
- Jinja2 模板引擎
- SQLAlchemy 数据库 ORM
- WTForms 表单处理库
- Flask-WTF 表单扩展库
- Flask-Login 用户认证库
### 项目环境
在开始项目前,需要配置好 Python 的开发环境。可以使用 virtualenv 创建一个虚拟环境:
```shell
$ virtualenv venv
$ source venv/bin/activate
```
接下来,需要安装 Flask 及其相关扩展:
```shell
$ pip install Flask
$ pip install Jinja2
$ pip install SQLAlchemy
$ pip install WTForms
$ pip install Flask-WTF
$ pip install Flask-Login
```
### 项目结构
在线商城的项目结构如下:
```
online-shop/
├── app/
│ ├── static/
│ │ ├── css/
│ │ │ ├── main.css
│ │ ├── js/
│ │ │ ├── main.js
│ ├── templates/
│ │ ├── base.html
│ │ ├── home.html
│ │ ├── login.html
│ │ ├── product.html
│ │ └── register.html
│ ├── __init__.py
│ ├── forms.py
│ ├── models.py
│ ├── routes.py
│ ├── config.py
│ └── extensions.py
├── run.py
└── requirements.txt
```
其中,`app` 文件夹是项目的主要代码目录,包含了应用程序的模板、视图、数据库模型以及配置信息。`static` 文件夹存放静态资源,如 CSS、JavaScript、图片等。`templates` 文件夹存放 HTML 模板文件。`run.py` 是启动应用程序的入口文件。`requirements.txt` 是项目依赖的 Python 库列表。
### 数据库设计
在线商城需要使用数据库来存储商品信息、用户信息以及订单信息。本项目中,我们选择使用 MySQL 数据库,采用 SQLAlchemy ORM 来进行数据访问。
首先需要在 MySQL 中创建一个名为 `online_shop` 的数据库。然后,定义数据库模型如下:
```python
from app.extensions import db
from flask_login import UserMixin
class Product(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(128), nullable=False)
price = db.Column(db.Float, nullable=False)
description = db.Column(db.String(256), nullable=False)
image_url = db.Column(db.String(256), nullable=False)
class User(UserMixin, db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(64), unique=True, nullable=False)
email = db.Column(db.String(128), unique=True, nullable=False)
password = db.Column(db.String(128), nullable=False)
orders = db.relationship('Order', backref='user', lazy=True)
class Order(db.Model):
id = db.Column(db.Integer, primary_key=True)
user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
product_id = db.Column(db.Integer, db.ForeignKey('product.id'), nullable=False)
quantity = db.Column(db.Integer, nullable=False)
total_price = db.Column(db.Float, nullable=False)
```
其中,`Product` 表用于存储商品信息,包括商品名称、价格、描述、图片 URL 等。`User` 表用于存储用户信息,包括用户名、电子邮件地址、密码等。`Order` 表用于存储订单信息,包括用户ID、商品ID、购买数量以及总价。
### 视图函数
在线商城的视图函数主要包括商品展示、购买、支付等功能。其中,需要使用到 Flask 的模板引擎 Jinja2 来渲染 HTML 页面,也需要使用 Flask-WTF 扩展库来处理用户注册和登录表单。此外,为了保障用户信息的安全,我们还需要使用 Flask-Login 扩展库来进行用户认证和授权。
在本项目中,定义了如下视图函数:
```python
from app import app, db
from app.forms import RegistrationForm, LoginForm
from app.models import User, Product, Order
from flask import render_template, url_for, redirect, flash
from flask_login import login_user, logout_user, login_required, current_user
@app.route('/')
def home():
products = Product.query.all()
return render_template('home.html', products=products)
@app.route('/product/')
@login_required
def product(product_id):
product = Product.query.get_or_404(product_id)
return render_template('product.html', product=product)
@app.route('/buy/', methods=['GET', 'POST'])
@login_required
def buy(product_id):
product = Product.query.get_or_404(product_id)
order = Order.query.filter_by(product_id=product.id, user_id=current_user.id).first()
if order:
order.quantity += 1
order.total_price += product.price
db.session.commit()
else:
order = Order(product_id=product.id, user_id=current_user.id, quantity=1, total_price=product.price)
db.session.add(order)
db.session.commit()
return redirect(url_for('cart'))
@app.route('/cart')
@login_required
def cart():
orders = Order.query.filter_by(user_id=current_user.id)
return render_template('cart.html', orders=orders)
@app.route('/remove/')
@login_required
def remove(order_id):
order = Order.query.get_or_404(order_id)
db.session.delete(order)
db.session.commit()
return redirect(url_for('cart'))
@app.route('/register', methods=['GET', 'POST'])
def register():
form = RegistrationForm()
if form.validate_on_submit():
user = User(username=form.username.data, email=form.email.data, password=form.password.data)
db.session.add(user)
db.session.commit()
flash('Congratulations, you are now a registered user!')
return redirect(url_for('login'))
return render_template('register.html', title='Register', form=form)
@app.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 is None or not user.check_password(form.password.data):
flash('Invalid email address or password')
return redirect(url_for('login'))
login_user(user, remember=form.remember_me.data)
return redirect(url_for('home'))
return render_template('login.html', title='Sign In', form=form)
@app.route('/logout')
def logout():
logout_user()
return redirect(url_for('home'))
```
其中,`home` 函数负责显示所有商品,`product` 函数负责显示单个商品的详细信息,`buy` 函数负责将商品添加到购物车中,`cart` 函数负责显示当前用户的购物车,`remove` 函数负责从购物车中删除项,`register` 函数负责用户注册,`login` 函数负责用户登录,`logout` 函数负责用户注销。
### 表单处理
为了实现用户注册和登录功能,我们需要使用到 Flask-WTF 扩展库来处理用户注册和登录表单。
在 `forms.py` 文件中,定义了如下表单类:
```python
from flask_wtf import FlaskForm
from wtforms import StringField, PasswordField, BooleanField, SubmitField
from wtforms.validators import DataRequired, Email, EqualTo
class RegistrationForm(FlaskForm):
username = StringField('Username', validators=[DataRequired()])
email = StringField('Email', validators=[DataRequired(), Email()])
password = PasswordField('Password', validators=[DataRequired()])
password2 = PasswordField('Repeat Password', validators=[DataRequired(), EqualTo('password')])
submit = SubmitField('Register')
class LoginForm(FlaskForm):
email = StringField('Email', validators=[DataRequired(), Email()])
password = PasswordField('Password', validators=[DataRequired()])
remember_me = BooleanField('Remember Me')
submit = SubmitField('Sign In')
```
其中,`RegistrationForm` 类用于处理用户注册表单,包括用户名、电子邮件地址、密码等。`LoginForm` 类用于处理用户登录表单,包括电子邮件地址、密码以及是否记住用户登录状态等。
### 用户认证和授权
为了保障用户信息的安全,需要使用 Flask-Login 扩展库来进行用户认证和授权。
在 `extensions.py` 文件中,定义了如下应用程序扩展:
```python
from flask_sqlalchemy import SQLAlchemy
from flask_login import LoginManager
db = SQLAlchemy()
login = LoginManager()
login.login_view = 'login'
```
其中,`db` 变量是 SQLAlchemy 数据库 ORM 对象,用于操作 MySQL 数据库。`login` 变量是 Flask-Login 对象,用于进行用户认证和授权。`login.login_view` 变量指定了用户未经认证时跳转到登录页面。
在 `__init__.py` 文件中,进行应用程序扩展的初始化操作:
```python
from flask import Flask
from app.config import Config
from app.extensions import db, login
def create_app():
app = Flask(__name__)
app.config.from_object(Config)
db.init_app(app)
login.init_app(app)
from app.routes import home, product, buy, cart, remove, register, login, logout
app.register_blueprint(home)
app.register_blueprint(product)
app.register_blueprint(buy)
app.register_blueprint(cart)
app.register_blueprint(remove)
app.register_blueprint(register)
app.register_blueprint(login)
app.register_blueprint(logout)
return app
```
其中,`create_app` 函数用于创建 Flask 应用程序对象,并初始化数据库 ORM 和用户认证对象。由于应用程序比较复杂,使用了蓝图(Blueprint)来分离不同模块的视图函数。
### 运行应用程序
在 `run.py` 文件中,启动了 Flask 应用程序:
```python
from app import create_app
app = create_app()
if __name__ == '__main__':
app.run()
```
运行项目时,需要使用 Flask-WTF 扩展库自动生成 CSRF 保护字段,可以在 HTML 页面中使用如下代码:
```html
```
此外,还需要在 MySQL 数据库中创建一个管理员账号,在 `models.py` 文件中增加如下代码:
```python
from werkzeug.security import generate_password_hash
admin = User(username='admin', email='admin@example.com', password=generate_password_hash('admin'))
db.session.add(admin)
db.session.commit()
```
以上就是基于 Flask 的在线商城开发的详细介绍。通过本项目的实战,可以更深入地了解 Flask Web 开发框架的使用,包括 Web 应用程序的开发流程、数据库操作、用户认证和授权等方面的实践。