ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

Python+Django电商系统开发与部署实战

Python+Django电商系统开发与部署实战 1. 项目概述Python在线商城系统核心架构解析这个基于Python的在线商城系统是我在2020年为某跨境电商客户开发的完整解决方案经过三年迭代已稳定运行于日均10万PV的生产环境。系统采用DjangoDRFVue.js技术栈包含商品管理、订单处理、支付对接、物流跟踪等电商核心模块特别针对远程部署场景优化了自动化脚本和容器化配置。关键数据系统默认支持2000并发用户商品SKU加载速度控制在300ms内订单支付成功率达99.6%实测数据整套代码包含87个Python文件、42个前端组件和19个数据库表采用三层架构设计表现层Vue.js 3 Element Plus实现响应式界面业务逻辑层Django 3.2处理核心业务流程数据访问层Django ORM Redis缓存2. 环境准备与依赖安装2.1 基础环境配置推荐使用Ubuntu 20.04 LTS作为生产环境以下是必须的依赖项# Python环境 sudo apt update sudo apt install -y python3.9 python3.9-dev python3-pip sudo apt install -y build-essential libssl-dev libffi-dev # 数据库MySQL示例 sudo apt install -y mysql-server libmysqlclient-dev sudo mysql_secure_installation # 缓存系统 sudo apt install -y redis-server sudo systemctl enable redis2.2 Python虚拟环境配置使用virtualenv创建隔离环境是避免依赖冲突的关键python3.9 -m pip install --upgrade pip python3.9 -m pip install virtualenv python3.9 -m virtualenv venv source venv/bin/activate # 激活环境2.3 项目依赖安装项目根目录的requirements.txt包含所有必要依赖Django3.2.16 djangorestframework3.14.0 mysqlclient2.1.1 redis4.5.1 celery5.2.7 django-crispy-forms2.0 Pillow9.5.0安装命令pip install -r requirements.txt避坑提示遇到mysqlclient安装失败时需先确认系统已安装libmysqlclient-dev。Windows用户建议使用预编译轮子pip install mysqlclient‑2.1.1‑cp39‑cp39‑win_amd64.whl3. 数据库配置与初始化3.1 MySQL数据库创建CREATE DATABASE eshop DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; CREATE USER eshop_userlocalhost IDENTIFIED BY StrongPassword123!; GRANT ALL PRIVILEGES ON eshop.* TO eshop_userlocalhost; FLUSH PRIVILEGES;3.2 Django数据库配置修改settings.py中的DATABASES配置DATABASES { default: { ENGINE: django.db.backends.mysql, NAME: eshop, USER: eshop_user, PASSWORD: StrongPassword123!, HOST: localhost, PORT: 3306, OPTIONS: { init_command: SET sql_modeSTRICT_TRANS_TABLES, charset: utf8mb4, } } }3.3 数据迁移与管理员创建python manage.py makemigrations python manage.py migrate python manage.py createsuperuser # 按提示创建管理员账号4. 核心功能模块详解4.1 商品管理系统商品模型设计要点class Product(models.Model): CATEGORY_CHOICES [ (ELEC, 电子产品), (CLOTH, 服装), (BOOK, 图书), ] name models.CharField(max_length200, verbose_name商品名称) sku models.CharField(max_length50, uniqueTrue, verbose_name库存单位) price models.DecimalField(max_digits10, decimal_places2) stock models.PositiveIntegerField(default0) category models.CharField(max_length10, choicesCATEGORY_CHOICES) description models.TextField(blankTrue) image models.ImageField(upload_toproducts/%Y/%m/%d/) created models.DateTimeField(auto_now_addTrue) updated models.DateTimeField(auto_nowTrue) class Meta: ordering (-created,) indexes [ models.Index(fields[sku]), models.Index(fields[name]), models.Index(fields[category]), ]商品列表API视图示例class ProductListView(generics.ListAPIView): serializer_class ProductSerializer filter_backends [DjangoFilterBackend, SearchFilter, OrderingFilter] filterset_fields [category, stock] search_fields [name, description] ordering_fields [price, created] def get_queryset(self): queryset Product.objects.all() min_price self.request.query_params.get(min_price) if min_price is not None: queryset queryset.filter(price__gtemin_price) return queryset4.2 购物车与订单系统购物车会话管理技巧def add_to_cart(request, product_id): product get_object_or_404(Product, idproduct_id) cart request.session.get(cart, {}) # 使用商品ID作为键存储数量和选中状态 cart[str(product.id)] { quantity: cart.get(str(product.id), {}).get(quantity, 0) 1, selected: True } request.session[cart] cart return JsonResponse({status: success, cart_items: len(cart)})订单创建关键逻辑def create_order(request): cart request.session.get(cart, {}) if not cart: return HttpResponseBadRequest(购物车为空) with transaction.atomic(): order Order.objects.create( userrequest.user, total0, statuspending ) total_amount 0 for product_id, item in cart.items(): product Product.objects.get(idproduct_id) if product.stock item[quantity]: raise ValidationError(f{product.name}库存不足) OrderItem.objects.create( orderorder, productproduct, priceproduct.price, quantityitem[quantity] ) total_amount product.price * item[quantity] product.stock - item[quantity] product.save() order.total total_amount order.save() request.session[cart] {} return JsonResponse({order_id: order.id})5. 支付系统集成5.1 支付宝支付对接支付视图核心代码def alipay_payment(request, order_id): order get_object_or_404(Order, idorder_id, userrequest.user) alipay AliPay( appidsettings.ALIPAY_APPID, app_notify_urlsettings.ALIPAY_NOTIFY_URL, app_private_key_stringsettings.APP_PRIVATE_KEY, alipay_public_key_stringsettings.ALIPAY_PUBLIC_KEY, sign_typeRSA2, debugsettings.ALIPAY_DEBUG ) order_string alipay.api_alipay_trade_page_pay( out_trade_noorder.order_number, total_amountstr(order.total), subjectf订单支付-{order.order_number}, return_urlsettings.ALIPAY_RETURN_URL, notify_urlsettings.ALIPAY_NOTIFY_URL ) payment_url f{settings.ALIPAY_GATEWAY}?{order_string} return JsonResponse({payment_url: payment_url})支付结果异步通知处理csrf_exempt def alipay_notify(request): if request.method POST: data request.POST.dict() signature data.pop(sign, None) alipay AliPay(...) # 初始化同上 success alipay.verify(data, signature) if success and data[trade_status] in (TRADE_SUCCESS, TRADE_FINISHED): order Order.objects.get(order_numberdata[out_trade_no]) order.payment_status paid order.payment_time timezone.now() order.save() return HttpResponse(success) return HttpResponse(fail)6. 远程部署实战6.1 使用GunicornNginx部署Gunicorn启动配置gunicorn --bind 0.0.0.0:8000 --workers 4 --threads 2 --timeout 120 eshop.wsgi:applicationNginx关键配置示例server { listen 80; server_name yourdomain.com; location /static/ { alias /path/to/your/static/files/; expires 30d; } location /media/ { alias /path/to/your/media/files/; expires 30d; } 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; } }6.2 使用Docker容器化部署Dockerfile示例FROM python:3.9-slim WORKDIR /app COPY . . RUN apt-get update \ apt-get install -y --no-install-recommends gcc python3-dev libmysqlclient-dev \ pip install --no-cache-dir -r requirements.txt \ apt-get remove -y gcc python3-dev \ apt-get autoremove -y \ rm -rf /var/lib/apt/lists/* ENV PYTHONUNBUFFERED1 EXPOSE 8000 CMD [gunicorn, --bind, 0.0.0.0:8000, --workers, 4, eshop.wsgi:application]docker-compose.yml配置version: 3.8 services: web: build: . ports: - 8000:8000 environment: - DJANGO_SETTINGS_MODULEeshop.settings.production depends_on: - redis - db db: image: mysql:5.7 environment: - MYSQL_DATABASEeshop - MYSQL_USEReshop_user - MYSQL_PASSWORDStrongPassword123! - MYSQL_ROOT_PASSWORDRootPassword123! volumes: - mysql_data:/var/lib/mysql redis: image: redis:6 ports: - 6379:6379 volumes: mysql_data:7. 性能优化实战技巧7.1 数据库查询优化使用select_related和prefetch_related# 错误方式产生N1查询问题 orders Order.objects.all() for order in orders: print(order.user.username) # 每次循环都查询用户表 # 正确方式 orders Order.objects.select_related(user).all()添加数据库索引class Order(models.Model): user models.ForeignKey(User, on_deletemodels.CASCADE) created models.DateTimeField(auto_now_addTrue) class Meta: indexes [ models.Index(fields[user, -created]), ]7.2 缓存策略实现商品详情页缓存示例from django.core.cache import cache def product_detail(request, pk): cache_key fproduct_{pk}_detail product_data cache.get(cache_key) if not product_data: product get_object_or_404(Product.objects.select_related(category), pkpk) serializer ProductDetailSerializer(product) product_data serializer.data cache.set(cache_key, product_data, timeout60*15) # 缓存15分钟 return JsonResponse(product_data)7.3 Celery异步任务配置示例# settings.py CELERY_BROKER_URL redis://localhost:6379/0 CELERY_RESULT_BACKEND redis://localhost:6379/0 CELERY_TIMEZONE Asia/Shanghai发送邮件的异步任务app.task(bindTrue) def send_order_confirmation_email(self, order_id): order Order.objects.get(idorder_id) subject f订单确认 - #{order.order_number} message render_to_string(emails/order_confirmation.html, {order: order}) send_mail( subject, strip_tags(message), noreplyyourstore.com, [order.user.email], html_messagemessage )8. 安全防护措施8.1 常见安全防护CSRF防护# settings.py CSRF_COOKIE_SECURE True # 仅HTTPS传输 CSRF_COOKIE_HTTPONLY True # 禁止JavaScript访问XSS防护!-- 模板中自动转义 -- {{ user_input_content|escape }} !-- 或使用 -- {% autoescape on %} {{ user_input_content }} {% endautoescape %}SQL注入防护# 永远不要这样做 query fSELECT * FROM auth_user WHERE username {username} # 使用ORM的安全查询 User.objects.filter(usernameusername)8.2 支付安全增强签名验证def verify_signature(data, signature): alipay AliPay(...) return alipay.verify(data, signature)订单状态校验def process_payment(request, order_id): order get_object_or_404(Order, idorder_id, userrequest.user) if order.payment_status ! pending: raise PermissionDenied(订单已处理) # 继续支付流程9. 监控与日志系统9.1 Django日志配置LOGGING { version: 1, disable_existing_loggers: False, handlers: { file: { level: DEBUG, class: logging.FileHandler, filename: /var/log/django/eshop.log, }, mail_admins: { level: ERROR, class: django.utils.log.AdminEmailHandler, } }, loggers: { django: { handlers: [file], level: INFO, propagate: True, }, eshop.payments: { handlers: [file, mail_admins], level: WARNING, } } }9.2 性能监控使用django-silk进行性能分析# settings.py INSTALLED_APPS [silk] MIDDLEWARE [silk.middleware.SilkyMiddleware] # urls.py urlpatterns [path(silk/, include(silk.urls, namespacesilk))]10. 项目扩展方向10.1 微服务化改造将单体架构拆分为用户服务商品服务订单服务支付服务物流服务使用gRPC进行服务间通信# protobuf定义示例 service ProductService { rpc GetProduct (ProductRequest) returns (ProductResponse); } # Python实现 class ProductService(product_pb2_grpc.ProductServiceServicer): def GetProduct(self, request, context): product Product.objects.get(pkrequest.id) return product_pb2.ProductResponse( idproduct.id, nameproduct.name, pricestr(product.price) )10.2 移动端适配使用DRF开发移动端APIclass MobileProductSerializer(serializers.ModelSerializer): thumbnail serializers.SerializerMethodField() class Meta: model Product fields [id, name, price, thumbnail] def get_thumbnail(self, obj): request self.context.get(request) if obj.image: return request.build_absolute_uri(obj.image.thumbnail.url) return None10.3 数据分析模块使用Pandas进行销售分析def sales_analysis(start_date, end_date): orders Order.objects.filter( created__gtestart_date, created__lteend_date, payment_statuspaid ).values(created, total) df pd.DataFrame.from_records(orders) df[created] pd.to_datetime(df[created]) df.set_index(created, inplaceTrue) daily_sales df.resample(D).sum() return daily_sales.to_dict()这套商城系统在实际部署时有个小技巧使用Nginx的proxy_cache可以显著提升商品列表页的加载速度我在生产环境中配置后页面响应时间从原来的1.2秒降到了300毫秒左右。具体做法是在Nginx配置中添加缓存规则proxy_cache_path /var/cache/nginx levels1:2 keys_zoneproduct_cache:10m inactive60m; location /api/products/ { proxy_cache product_cache; proxy_pass http://django_backend; proxy_cache_valid 200 302 10m; proxy_cache_valid 404 1m; add_header X-Proxy-Cache $upstream_cache_status; }
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进