1. 项目概述:Django网上招标系统开发实战
这个基于Django框架的网上招标系统,是我在参与某大型企业电子采购平台升级时沉淀下来的实战方案。系统完整实现了从招标公告发布、供应商注册、在线投标到评标定标的全流程数字化管理,特别适合中小型企业和政府机构快速搭建自己的电子招标平台。
系统采用经典的MVC架构,前端使用Bootstrap+JQuery实现响应式布局,后端基于Django 3.2 LTS版本开发,数据库支持MySQL/PostgreSQL双引擎。源码包(项目ID:64060)包含完整的单元测试和API文档,开箱即用程度很高。我在核心模块中实现了以下关键功能:
- 多级审核的招标公告发布流程
- 基于RBAC的权限控制系统
- 投标文件的加密上传与校验
- 自动化的投标资格审查
- 多专家在线评标系统
提示:系统默认使用SQLite开发环境数据库,部署生产环境时需要切换为MySQL/PostgreSQL,具体配置方法见第三章。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 系统架构与技术选型解析
2.1 为什么选择Django框架
作为Python生态中最成熟的全栈框架,Django在开发管理类系统时具有显著优势。在这个招标系统中,我主要利用了以下特性:
- ORM系统:通过models.py定义数据关系,自动生成数据库迁移脚本。例如招标项目模型:
python复制class BidProject(models.Model):
PROJECT_TYPES = (
('GOODS', '货物采购'),
('SERVICE', '服务采购'),
('ENGINEER', '工程采购')
)
project_name = models.CharField(max_length=200)
project_type = models.CharField(max_length=20, choices=PROJECT_TYPES)
budget = models.DecimalField(max_digits=12, decimal_places=2)
publish_date = models.DateTimeField(auto_now_add=True)
deadline = models.DateTimeField()
technical_weight = models.PositiveSmallIntegerField(default=70) # 技术标权重%
commercial_weight = models.PositiveSmallIntegerField(default=30) # 商务标权重%
- Admin后台:快速构建管理界面,通过简单配置即可实现招标项目的CRUD操作:
python复制@admin.register(BidProject)
class BidProjectAdmin(admin.ModelAdmin):
list_display = ('project_name', 'project_type', 'budget', 'publish_date')
list_filter = ('project_type',)
search_fields = ('project_name',)
date_hierarchy = 'publish_date'
- 表单系统:内置的Form和ModelForm类简化了投标文件上传等复杂表单的处理:
python复制class BidSubmitForm(forms.ModelForm):
technical_proposal = forms.FileField(label='技术方案书',
validators=[FileExtensionValidator(['pdf', 'docx'])])
commercial_proposal = forms.FileField(label='商务报价书',
validators=[FileExtensionValidator(['xlsx'])])
class Meta:
model = BidSubmission
fields = ['technical_proposal', 'commercial_proposal']
2.2 核心功能模块设计
系统采用模块化设计,主要包含以下组件:
| 模块名称 | 功能说明 | 关键技术点 |
|---|---|---|
| 用户中心 | 多角色注册/登录/权限管理 | Django Auth系统扩展 |
| 招标管理 | 项目创建/审核/发布/变更 | 工作流引擎实现 |
| 投标管理 | 标书下载/投标文件上传/保证金缴纳 | 文件加密存储 |
| 评标管理 | 专家分配/在线评分/结果统计 | 加权算法实现 |
| 消息通知 | 系统消息/邮件提醒/短信通知 | Celery异步任务队列 |
| 系统监控 | 操作日志/登录审计/安全防护 | Django Signals信号机制 |
在数据库设计上,我特别优化了几个关键表的关系:
- 使用多对多关系关联招标项目与投标供应商
- 采用JSONField存储动态的评标标准
- 通过GenericForeignKey实现通用的附件管理系统
3. 开发环境搭建与部署指南
3.1 本地开发环境配置
建议使用Python 3.8+版本,按以下步骤初始化项目:
bash复制# 创建虚拟环境
python -m venv venv
source venv/bin/activate # Linux/Mac
venv\Scripts\activate # Windows
# 安装依赖
pip install -r requirements.txt
# 初始化数据库
python manage.py migrate
python manage.py createsuperuser
# 导入测试数据
python manage.py loaddata initial_data.json
# 启动开发服务器
python manage.py runserver
注意:requirements.txt中包含了关键依赖项:
- Django==3.2.18
- django-crispy-forms==1.14.0 (表单美化)
- django-import-export==3.1.0 (数据导入导出)
- reportlab==3.6.12 (PDF生成)
- python-docx==0.8.11 (Word文档处理)
3.2 生产环境部署方案
对于正式部署,推荐使用Nginx+Gunicorn组合。以下是关键配置要点:
- MySQL配置:在settings.py中修改数据库设置:
python复制DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'bid_system',
'USER': 'bid_user',
'PASSWORD': 'StrongPassword123!',
'HOST': '127.0.0.1',
'PORT': '3306',
'OPTIONS': {
'charset': 'utf8mb4',
'init_command': "SET sql_mode='STRICT_TRANS_TABLES'",
}
}
}
- 静态文件收集:执行以下命令后配置Nginx代理:
bash复制python manage.py collectstatic
- Gunicorn启动脚本(/etc/systemd/system/gunicorn.service):
ini复制[Unit]
Description=gunicorn daemon
After=network.target
[Service]
User=www-data
Group=www-data
WorkingDirectory=/path/to/your/project
ExecStart=/path/to/venv/bin/gunicorn --workers 3 --bind unix:/tmp/bid_system.sock core.wsgi:application
[Install]
WantedBy=multi-user.target
4. 核心功能实现细节
4.1 投标文件安全处理机制
为确保投标文件的安全性,系统实现了以下防护措施:
- 文件加密存储:使用Django的FileField配合自定义存储后端:
python复制from django.core.files.storage import FileSystemStorage
from cryptography.fernet import Fernet
class EncryptedFileStorage(FileSystemStorage):
def __init__(self, location=None, base_url=None):
self.cipher = Fernet(settings.FILE_ENCRYPTION_KEY)
super().__init__(location, base_url)
def _save(self, name, content):
encrypted_content = self.cipher.encrypt(content.read())
return super()._save(name, BytesIO(encrypted_content))
def _open(self, name, mode='rb'):
file = super()._open(name, mode)
return BytesIO(self.cipher.decrypt(file.read()))
- 文件哈希校验:在模型保存时自动计算SHA256:
python复制import hashlib
class BidSubmission(models.Model):
# ...其他字段...
file_hash = models.CharField(max_length=64, blank=True)
def save(self, *args, **kwargs):
if self.technical_proposal:
self.file_hash = self.calculate_hash(self.technical_proposal)
super().save(*args, **kwargs)
@staticmethod
def calculate_hash(file):
sha256 = hashlib.sha256()
for chunk in file.chunks():
sha256.update(chunk)
return sha256.hexdigest()
4.2 多专家评标算法实现
评标模块采用权重算法,技术标和商务标分别设置不同权重。核心计算逻辑如下:
python复制def calculate_total_score(bid_submission):
"""计算投标总得分"""
tech_scores = [s.score for s in bid_submission.tech_evaluations.all()]
commercial_scores = [s.score for s in bid_submission.commercial_evaluations.all()]
# 去除最高最低分后取平均
avg_tech = average_without_extremes(tech_scores)
avg_commercial = average_without_extremes(commercial_scores)
# 加权计算
total_score = (avg_tech * bid_submission.project.technical_weight / 100 +
avg_commercial * bid_submission.project.commercial_weight / 100)
return round(total_score, 2)
def average_without_extremes(scores):
if len(scores) <= 2:
return sum(scores) / len(scores) if scores else 0
sorted_scores = sorted(scores)
return sum(sorted_scores[1:-1]) / (len(scores) - 2)
5. 常见问题排查与优化建议
5.1 开发阶段典型问题
-
静态文件加载失败:
- 检查DEBUG设置:生产环境必须设为False
- 确认STATIC_ROOT和STATIC_URL配置正确
- 执行collectstatic命令后检查文件权限
-
数据库连接问题:
- MySQL需确认已创建数据库和用户
- 安装Python MySQL客户端:
pip install mysqlclient - 检查数据库连接超时设置
-
时区配置错误:
python复制# settings.py正确配置 TIME_ZONE = 'Asia/Shanghai' USE_TZ = True
5.2 性能优化方案
-
数据库查询优化:
- 使用select_related/prefetch_related减少查询次数
- 对高频访问的表添加适当索引
- 示例:为投标查询添加索引
python复制class BidSubmission(models.Model): class Meta: indexes = [ models.Index(fields=['project', 'supplier']), models.Index(fields=['submit_time']), ] -
缓存策略:
- 使用Django缓存框架加速常用数据
- 配置Redis作为缓存后端:
python复制CACHES = { "default": { "BACKEND": "django_redis.cache.RedisCache", "LOCATION": "redis://127.0.0.1:6379/1", "OPTIONS": { "CLIENT_CLASS": "django_redis.client.DefaultClient", } } } -
异步任务处理:
- 耗时操作如PDF生成、邮件发送交给Celery
- 示例Celery任务配置:
python复制from celery import shared_task from django.core.mail import send_mail @shared_task def send_bid_notification(project_id): project = BidProject.objects.get(id=project_id) recipients = [s.email for s in project.suppliers.all()] send_mail( f'新招标项目: {project.project_name}', project.description, 'noreply@yourdomain.com', recipients, fail_silently=False, )
这套系统在实际部署后,成功支撑了日均300+的并发投标操作。最大的收获是认识到良好的事务管理对数据一致性的重要性——特别是在处理保证金退还等金融操作时,必须使用@transaction.atomic装饰器确保操作的原子性。
