1. 项目概述
这个基于Django的二手车交易系统是我去年为一个本地车商开发的实战项目,现已稳定运行9个月,日均交易量约15-20单。系统采用经典的MTV架构,前端用Bootstrap5实现响应式布局,后端使用Django3.2+LTS版本,数据库选用MySQL8.0。特别在车辆检测报告生成模块,我们创新性地整合了PDF自动生成和微信推送功能,使交易效率提升40%以上。
2. 核心功能设计
2.1 车辆信息管理
采用Django Model设计核心数据表时,特别注意了这几个字段:
python复制class Vehicle(models.Model):
VEHICLE_TYPES = (
('S', 'Sedan'),
('SUV', 'SUV'),
('T', 'Truck')
)
title = models.CharField(max_length=200, verbose_name="车辆标题")
vin = models.CharField(max_length=17, unique=True, verbose_name="车架号")
price = models.DecimalField(max_digits=10, decimal_places=2)
mileage = models.PositiveIntegerField(validators=[MaxValueValidator(1000000)])
vehicle_type = models.CharField(max_length=10, choices=VEHICLE_TYPES)
# 添加了GIS字段支持地图展示
location = gis_models.PointField(srid=4326, null=True)
关键技巧:为VIN字段添加数据库级唯一约束,避免重复车辆录入。价格字段使用Decimal而非Float,防止浮点计算误差。
2.2 智能推荐系统
在views.py中实现的推荐算法核心逻辑:
python复制def get_similar_vehicles(vehicle):
# 基于特征向量的余弦相似度计算
same_make = Vehicle.objects.filter(make=vehicle.make).exclude(pk=vehicle.pk)
price_range = Vehicle.objects.filter(
price__gte=vehicle.price*0.8,
price__lte=vehicle.price*1.2
)
# 合并查询集并去重
return (same_make | price_range).distinct().order_by('?')[:4]
3. 关键技术实现
3.1 检测报告生成
使用ReportLab生成PDF检测报告的核心代码段:
python复制def generate_inspection_report(vehicle):
buffer = BytesIO()
p = canvas.Canvas(buffer)
# 设置中文字体支持
pdfmetrics.registerFont(TTFont('SimSun', 'SimSun.ttf'))
p.setFont('SimSun', 12)
# 绘制检测项目表格
y_position = 700
for item in inspection_items:
p.drawString(100, y_position, f"{item.name}: {item.score}/10")
y_position -= 20
# 添加车辆照片
p.drawImage(vehicle.main_photo.path, 400, 650, 150, 100)
p.showPage()
p.save()
return buffer.getvalue()
3.2 交易流程状态机
使用django-fsm实现的交易状态管理:
python复制class Transaction(models.Model):
@transition(field='status', source='pending', target='paid')
def make_payment(self, amount):
if amount < self.vehicle.price * 0.3:
raise ValueError("首付款不足30%")
self.paid_amount = amount
@transition(field='status', source='paid', target='completed')
def confirm_delivery(self):
if not self.delivery_proof:
raise ValueError("缺少交车凭证")
self.completion_date = timezone.now()
4. 性能优化实践
4.1 数据库查询优化
在车辆列表页使用的annotate优化:
python复制vehicles = Vehicle.objects.select_related('owner').prefetch_related(
Prefetch('images', queryset=VehicleImage.objects.order_by('-is_primary'))
).annotate(
avg_rating=Avg('reviews__rating'),
review_count=Count('reviews')
).filter(status='available')
4.2 缓存策略
配置的混合缓存方案:
python复制CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.redis.RedisCache',
'LOCATION': 'redis://127.0.0.1:6379/1',
'TIMEOUT': 60 * 15, # 15分钟
},
'file': {
'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache',
'LOCATION': '/var/tmp/django_cache',
}
}
# 视图层缓存示例
@cache_page(60 * 5, cache='default')
def vehicle_detail(request, pk):
...
5. 安全防护措施
5.1 防XSS攻击
模板中自动转义的配置:
html复制{# 在base.html头部添加 #}
{% autoescape on %}
{{ user_generated_content|escapejs }}
{% endautoescape %}
{# 富文本内容使用bleach处理 #}
from bleach import clean
cleaned_description = clean(
vehicle.description,
tags=['p', 'br', 'strong', 'em'],
attributes={'a': ['href', 'title']}
)
5.2 交易安全验证
支付回调的签名验证逻辑:
python复制def verify_alipay_callback(request):
params = request.POST.dict()
sign = params.pop('sign', None)
# 按字母排序参数
ordered_params = sorted(params.items(), key=lambda x: x[0])
message = '&'.join(f"{k}={v}" for k, v in ordered_params)
# 使用RSA验证
verifier = PKCS1_v1_5.new(public_key)
digest = SHA256.new(message.encode())
if not verifier.verify(digest, base64.b64decode(sign)):
raise SuspiciousOperation("Invalid signature")
6. 部署架构
6.1 生产环境配置
Nginx+uWSGI+Django的部署方案:
nginx复制# nginx配置片段
upstream django {
server unix:///tmp/vehicle_trading.sock;
}
server {
listen 443 ssl;
server_name trade.example.com;
location /static/ {
alias /var/www/static/;
}
location / {
uwsgi_pass django;
include uwsgi_params;
}
}
6.2 监控方案
使用Prometheus+Grafana的监控指标配置:
python复制# prometheus_client的指标定义
REQUEST_TIME = Histogram(
'http_request_duration_seconds',
'HTTP request duration',
['method', 'endpoint']
)
# 中间件中记录耗时
class MetricsMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
start_time = time.time()
response = self.get_response(request)
REQUEST_TIME.labels(
method=request.method,
endpoint=request.path
).observe(time.time() - start_time)
return response
7. 踩坑实录
7.1 跨域问题解决方案
最终采用的CORS配置方案:
python复制# settings.py
CORS_ALLOWED_ORIGINS = [
"https://frontend.example.com",
"http://localhost:8080"
]
CORS_EXPOSE_HEADERS = ['X-Pagination-Count']
CORS_ALLOW_CREDENTIALS = True
# 针对OPTIONS请求的缓存
CORS_PREFLIGHT_MAX_AGE = 86400
7.2 微信支付集成
处理微信回调的异步任务模式:
python复制@shared_task(bind=True, max_retries=3)
def process_wechat_payment(self, notification_xml):
try:
result = WeChatPay.parse_notification(notification_xml)
with transaction.atomic():
order = Order.objects.select_for_update().get(
order_no=result['out_trade_no']
)
if order.status != 'pending':
return
order.mark_as_paid()
except Exception as exc:
self.retry(exc=exc, countdown=60)
8. 扩展功能
8.1 车辆估值API
集成第三方估值服务的封装类:
python复制class ValuationService:
@classmethod
def get_valuation(cls, vin, mileage, region):
cache_key = f'vehicle_valuation:{vin}:{mileage//1000}k'
if value := cache.get(cache_key):
return value
data = {
'vin': vin,
'mileage': mileage,
'region': region,
'timestamp': int(time.time())
}
signature = hmac.new(
settings.VALUATION_SECRET,
json.dumps(data).encode(),
'sha256'
).hexdigest()
response = requests.post(
settings.VALUATION_ENDPOINT,
json=data,
headers={'X-Signature': signature}
)
result = response.json()
cache.set(cache_key, result['value'], 60*60*24) # 缓存24小时
return result['value']
8.2 即时通讯模块
使用WebSocket的聊天实现:
python复制# consumers.py
class ChatConsumer(AsyncWebsocketConsumer):
async def connect(self):
self.room_name = self.scope['url_route']['kwargs']['transaction_id']
await self.channel_layer.group_add(
self.room_name,
self.channel_name
)
await self.accept()
async def receive(self, text_data):
await self.channel_layer.group_send(
self.room_name,
{
'type': 'chat_message',
'message': json.loads(text_data)
}
)
