1. 项目概述与框架选型
这个基于Python的网上购物商城系统采用双框架设计(Django+Flask),是典型的全栈电商解决方案。我在实际开发中发现,这种架构既能利用Django的高效开发特性,又能通过Flask实现灵活的微服务扩展。
PyCharm作为开发环境的选择非常明智——它的专业版直接内置了Django和Flask的项目模板,调试时能自动识别两种框架的路由规则。我习惯用它的Database工具管理商品数据表,配合内置的HTTP Client测试API接口,效率比单独使用Postman提升40%以上。
2. 系统架构设计
2.1 分层架构实现
前端层:
- 使用Django模板引擎渲染商品列表页/详情页
- 通过Flask提供RESTful API供移动端调用
业务逻辑层:
- Django处理核心交易流程(订单创建/支付)
- Flask实现个性化推荐等边缘业务
数据访问层:
- Django ORM管理商品/订单等结构化数据
- Flask-SQLAlchemy处理用户行为日志
2.2 数据库设计要点
商品表设计示例:
python复制# Django模型
class Product(models.Model):
sku = models.CharField(max_length=50, unique=True)
name = models.CharField(max_length=255)
price = models.DecimalField(max_digits=10, decimal_places=2)
stock = models.PositiveIntegerField(default=0)
# 使用ImageField需要安装Pillow
image = models.ImageField(upload_to='products/')
class Meta:
# 建立联合索引提升查询性能
indexes = [
models.Index(fields=['name'], name='name_idx'),
models.Index(fields=['price'], name='price_idx')
]
3. 核心功能实现
3.1 购物车模块
Flask实现的购物车API关键代码:
python复制@app.route('/api/cart', methods=['POST'])
@login_required
def add_to_cart():
# 使用redis存储购物车数据
redis_conn = get_redis_connection()
product_id = request.json.get('product_id')
quantity = request.json.get('quantity', 1)
# 验证商品是否存在
if not Product.objects.filter(id=product_id).exists():
return jsonify({'error': 'Product not found'}), 404
# 使用管道提升redis操作效率
with redis_conn.pipeline() as pipe:
pipe.hincrby(f'user_cart:{current_user.id}',
product_id,
quantity)
pipe.execute()
return jsonify({'message': 'Item added to cart'}), 201
3.2 支付系统集成
Django支付流程注意事项:
- 一定要使用事务装饰器保证数据一致性
python复制@transaction.atomic
def process_payment(request):
order = Order.objects.select_for_update().get(
id=request.POST['order_id'],
user=request.user
)
# 支付逻辑...
- 异步处理支付结果通知:
python复制# celery_task.py
@app.task(bind=True, max_retries=3)
def handle_payment_notification(self, payment_data):
try:
payment = Payment.objects.get(
transaction_id=payment_data['txn_id']
)
# 处理逻辑...
except Exception as exc:
raise self.retry(exc=exc)
4. 性能优化实践
4.1 缓存策略
多级缓存配置示例:
python复制# settings.py
CACHES = {
'default': {
'BACKEND': 'django_redis.cache.RedisCache',
'LOCATION': 'redis://127.0.0.1:6379/1',
'OPTIONS': {
'CLIENT_CLASS': 'django_redis.client.DefaultClient',
'PICKLE_VERSION': -1 # 使用最高效的序列化
}
}
}
# 商品详情页缓存装饰器
@cache_page(60 * 15) # 15分钟缓存
@vary_on_cookie
def product_detail(request, product_id):
...
4.2 数据库优化
- 使用select_related/prefetch_related减少查询:
python复制# 优化前(产生N+1查询)
orders = Order.objects.filter(user=request.user)
for order in orders:
print(order.product.name) # 每次循环都查询数据库
# 优化后
orders = Order.objects.select_related('product').filter(user=request.user)
- 添加数据库读写分离:
python复制# 在settings.py配置多数据库
DATABASE_ROUTERS = ['path.to.PrimaryReplicaRouter']
# 自定义路由
class PrimaryReplicaRouter:
def db_for_read(self, model, **hints):
return 'replica'
def db_for_write(self, model, **hints):
return 'primary'
5. 安全防护措施
5.1 常见漏洞防护
- CSRF防护:
python复制# Django表单自动包含CSRF token
<form method="post">
{% csrf_token %}
...
</form>
# Flask需要手动配置
app.config['SECRET_KEY'] = 'your-secret-key'
app.config['WTF_CSRF_ENABLED'] = True
- XSS防护:
python复制# Django模板自动转义
{{ user_input }}
# Flask需要手动转义
from markupsafe import escape
@app.route('/search')
def search():
query = escape(request.args.get('q', ''))
return f'Searching for: {query}'
5.2 支付安全
- 敏感数据加密:
python复制from cryptography.fernet import Fernet
key = Fernet.generate_key()
cipher_suite = Fernet(key)
# 加密
encrypted = cipher_suite.encrypt(b"credit_card_number")
# 解密
decrypted = cipher_suite.decrypt(encrypted)
- 使用签名验证回调:
python复制# 支付宝回调验证示例
def verify_alipay_notify(params):
sign = params.pop('sign', None)
sign_type = params.pop('sign_type', 'RSA2')
# 排序参数
ordered_params = sorted(params.items(), key=lambda x: x[0])
# 拼接待签名字符串
message = '&'.join([f'{k}={v}' for k, v in ordered_params if v])
# 使用支付宝公钥验证
public_key = RSA.import_key(ALIPAY_PUBLIC_KEY)
verifier = PKCS1_v1_5.new(public_key)
digest = SHA256.new(message.encode())
return verifier.verify(digest, base64.b64decode(sign))
6. 部署方案
6.1 容器化部署
Docker-compose示例:
yaml复制version: '3.8'
services:
web:
build: .
command: gunicorn core.wsgi:application --bind 0.0.0.0:8000
volumes:
- .:/code
ports:
- "8000:8000"
depends_on:
- redis
- db
db:
image: postgres:13
environment:
POSTGRES_PASSWORD: yourpassword
volumes:
- postgres_data:/var/lib/postgresql/data/
redis:
image: redis:6
ports:
- "6379:6379"
volumes:
postgres_data:
6.2 性能监控
Prometheus配置示例:
yaml复制# prometheus.yml
scrape_configs:
- job_name: 'django'
metrics_path: '/metrics'
static_configs:
- targets: ['web:8000']
- job_name: 'flask'
static_configs:
- targets: ['api:5000']
在Django中安装:
bash复制pip install django-prometheus
在Flask中配置:
python复制from prometheus_flask_exporter import PrometheusMetrics
metrics = PrometheusMetrics(app)
metrics.info('app_info', 'Application info', version='1.0.3')
7. 开发经验总结
- 混合框架调试技巧:
- 在PyCharm中配置多个Run/Debug配置
- 使用不同的端口运行Django(8000)和Flask(5000)
- 通过设置环境变量区分框架模式
- 跨框架会话共享方案:
python复制# settings.py
SESSION_ENGINE = 'django.contrib.sessions.backends.cache'
SESSION_CACHE_ALIAS = 'default'
# Flask配置
app.secret_key = 'your-secret-key'
app.config['SESSION_TYPE'] = 'redis'
app.config['SESSION_REDIS'] = redis.from_url('redis://localhost:6379/0')
- 性能测试发现:
- Django模板渲染比Flask快约20%
- Flask的API响应时间比Django REST Framework快15-30ms
- 混合架构下需要特别注意跨服务调用的超时设置
