1. 项目背景与核心需求
办公用品采购系统是企事业单位日常运营中不可或缺的基础设施。传统的手工登记采购方式效率低下、容易出错,且难以进行数据统计和分析。作为一名计算机专业的学生,选择这个课题作为毕业设计既贴合实际应用场景,又能全面锻炼Web开发能力。
Django作为Python生态中最成熟的Web框架之一,其"开箱即用"的特性特别适合快速构建此类管理系统。它内置了强大的ORM、Admin后台、用户认证等核心功能,可以让我们把精力集中在业务逻辑的实现上,而不是重复造轮子。
这个系统需要解决的核心问题包括:
- 多角色权限管理(采购员、审批人、管理员等)
- 采购申请与审批流程的电子化
- 库存状态的实时监控与预警
- 采购历史记录的查询与统计
- 供应商信息的集中管理
2. 系统架构设计
2.1 技术选型分析
前端部分采用经典的Bootstrap+jQuery组合,虽然现在Vue/React更流行,但对于毕业设计项目来说,传统技术栈更容易上手且文档丰富。后端选择Django 3.2 LTS版本,这是目前最稳定的长期支持版。
数据库方面,考虑到系统数据关系明确但规模不大,使用Django内置的SQLite即可满足需求。如果考虑扩展性,可以轻松切换为MySQL或PostgreSQL,这正是Django ORM的优势所在。
2.2 核心数据模型设计
系统主要包含以下几个关键模型:
class Supplier(models.Model): name = models.CharField(max_length=100) contact = models.CharField(max_length=50) phone = models.CharField(max_length=20) address = models.TextField() class OfficeItem(models.Model): name = models.CharField(max_length=100) category = models.CharField(max_length=50) specification = models.TextField() unit = models.CharField(max_length=10) current_stock = models.IntegerField(default=0) min_stock = models.IntegerField(default=10) class PurchaseRequest(models.Model): requester = models.ForeignKey(User, on_delete=models.CASCADE) item = models.ForeignKey(OfficeItem, on_delete=models.CASCADE) quantity = models.IntegerField() request_date = models.DateTimeField(auto_now_add=True) status = models.CharField(max_length=20, choices=STATUS_CHOICES, default='pending') approver = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, related_name='approved_requests') approve_date = models.DateTimeField(null=True) reject_reason = models.TextField(blank=True)2.3 权限系统设计
Django自带的权限系统已经足够强大,我们只需要进行适当扩展:
from django.contrib.auth.models import Group purchaser_group, _ = Group.objects.get_or_create(name='Purchaser') approver_group, _ = Group.objects.get_or_create(name='Approver') admin_group, _ = Group.objects.get_or_create(name='Admin') # 在视图中检查权限 @permission_required('purchase.add_purchaserequest') def create_request(request): ...3. 核心功能实现
3.1 采购流程实现
采购流程是系统的核心,采用状态机模式进行设计:
from django_fsm import FSMField, transition class PurchaseRequest(models.Model): status = FSMField(default='draft') @transition(field=status, source='draft', target='submitted') def submit(self): """提交采购申请""" @transition(field=status, source='submitted', target='approved') def approve(self, approver): """审批通过""" self.approver = approver self.approve_date = timezone.now() @transition(field=status, source='submitted', target='rejected') def reject(self, approver, reason): """审批拒绝""" self.approver = approver self.approve_date = timezone.now() self.reject_reason = reason3.2 库存预警功能
在模型保存时自动检查库存水平:
from django.db.models.signals import post_save from django.dispatch import receiver @receiver(post_save, sender=OfficeItem) def check_stock_level(sender, instance, **kwargs): if instance.current_stock < instance.min_stock: # 发送邮件或站内通知 send_notification.delay( f"库存预警:{instance.name}当前库存{instance.current_stock}{instance.unit}," f"低于最低库存量{instance.min_stock}{instance.unit}" )3.3 数据统计与报表
使用Django ORM的聚合功能实现基础统计:
from django.db.models import Sum, Count from datetime import datetime, timedelta def get_purchase_stats(): # 最近30天的采购统计 start_date = datetime.now() - timedelta(days=30) stats = ( PurchaseRequest.objects .filter(status='approved', approve_date__gte=start_date) .values('item__name') .annotate(total_quantity=Sum('quantity'), count=Count('id')) .order_by('-total_quantity') ) return stats4. 开发中的关键问题与解决方案
4.1 并发修改问题
当多个用户同时操作同一物品库存时,可能出现竞态条件。解决方案是使用select_for_update:
from django.db import transaction @transaction.atomic def update_stock(item_id, quantity): item = OfficeItem.objects.select_for_update().get(pk=item_id) item.current_stock += quantity item.save()4.2 文件上传与处理
采购可能需要上传报价单等附件:
from django.core.files.storage import FileSystemStorage class PurchaseRequest(models.Model): attachment = models.FileField( upload_to='purchase_attachments/%Y/%m/%d', storage=FileSystemStorage(location=settings.MEDIA_ROOT), blank=True ) # settings.py中配置 MEDIA_ROOT = os.path.join(BASE_DIR, 'media') MEDIA_URL = '/media/'4.3 性能优化技巧
对于频繁访问但又很少变化的数据,如物品分类,可以使用缓存:
from django.core.cache import cache def get_categories(): categories = cache.get('office_item_categories') if not categories: categories = OfficeItem.objects.values_list('category', flat=True).distinct() cache.set('office_item_categories', categories, 3600) # 缓存1小时 return categories5. 项目部署与扩展建议
5.1 基础部署方案
最简单的部署方式是使用Django内置开发服务器+SQLite:
python manage.py migrate python manage.py createsuperuser python manage.py runserver 0.0.0.0:8000对于正式环境,推荐Nginx+Gunicorn组合:
# 安装Gunicorn pip install gunicorn # 启动命令 gunicorn --bind 0.0.0.0:8000 your_project.wsgi:application5.2 可能的扩展方向
- 工作流引擎集成:使用django-viewflow实现更复杂的审批流程
- 移动端适配:开发REST API供移动端调用
- 数据分析:集成Pandas进行更深入的数据分析
- 自动化采购:设置自动补货规则,当库存低于阈值时自动生成采购单
5.3 项目文档编写建议
良好的文档是毕业设计的重要加分项,建议包含:
- 需求分析文档
- 系统设计文档
- 数据库设计文档
- 用户手册
- 部署指南
可以使用Sphinx自动生成API文档:
pip install sphinx sphinx-quickstart docs6. 源码结构与关键文件说明
项目采用标准的Django项目结构:
office_purchase/ ├── manage.py ├── office_purchase/ │ ├── __init__.py │ ├── settings.py │ ├── urls.py │ └── wsgi.py ├── purchase/ # 主应用 │ ├── migrations/ │ ├── __init__.py │ ├── admin.py │ ├── apps.py │ ├── models.py │ ├── tests.py │ ├── urls.py │ └── views.py ├── templates/ # 前端模板 │ ├── base.html │ ├── purchase/ │ │ ├── item_list.html │ │ └── request_form.html └── static/ # 静态文件 ├── css/ └── js/关键文件说明:
purchase/models.py:包含所有数据模型定义purchase/views.py:业务逻辑实现purchase/admin.py:后台管理配置templates/base.html:基础模板文件
7. 常见问题排查
7.1 管理员后台无法登录
确保已创建超级用户:
python manage.py createsuperuser检查settings.py中的认证后端配置:
AUTHENTICATION_BACKENDS = [ 'django.contrib.auth.backends.ModelBackend', ]7.2 静态文件无法加载
开发环境下需要在urls.py中添加:
from django.conf import settings from django.conf.urls.static import static urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)生产环境下需要配置Nginx/Apache正确服务静态文件。
7.3 数据库迁移问题
如果修改模型后迁移出错,可以尝试:
# 删除迁移文件(除了__init__.py) # 删除数据库 # 重新生成迁移 python manage.py makemigrations python manage.py migrate8. 项目演示与答辩准备
8.1 演示要点
核心流程演示:
- 用户登录
- 创建采购申请
- 审批流程
- 库存查看
特色功能展示:
- 库存预警
- 数据统计
- 权限控制
技术亮点说明:
- Django ORM的使用
- 状态机实现审批流程
- 信号机制实现库存监控
8.2 答辩常见问题准备
- 为什么选择Django而不是其他框架?
- 系统如何处理高并发情况?
- 如何保证数据的安全性和一致性?
- 系统的扩展性体现在哪些方面?
- 开发过程中遇到的最大挑战是什么?如何解决的?
8.3 项目改进方向
- 引入Celery实现异步任务处理
- 增加REST API支持移动端
- 实现更细粒度的权限控制
- 加入操作日志审计功能
- 优化前端交互体验
在实际开发这个系统的过程中,我发现Django的Admin后台虽然强大,但直接使用原生的界面会显得项目不够专业。一个实用的技巧是使用django-admin-interface这样的第三方包来美化后台,这只需要几行配置就能显著提升项目的外观档次。另外,对于需要频繁操作的功能,如采购申请,可以添加一些快捷键操作,这能极大提升用户体验。