1. 项目概述
这个基于Django的宠物寄养平台是我去年完成的毕业设计项目,从需求分析到最终部署上线总共花了3个月时间。作为一个养了两只猫的铲屎官,我发现在城市里临时出差或旅游时,找个靠谱的地方寄养宠物特别麻烦。现有的宠物店寄养价格高、环境拥挤,而个人寄养又缺乏保障。这就是我做这个平台的初衷——搭建一个连接宠物主人和寄养家庭的C2C平台。
平台核心功能包括:
- 用户系统:分为宠物主人、寄养家庭、管理员三种角色
- 宠物档案管理:记录宠物基本信息、疫苗情况、特殊需求
- 寄养订单系统:支持预约、支付、评价全流程
- 地图服务:基于LBS的附近寄养家庭搜索
- 消息通知:站内信+邮件+短信的多渠道提醒
技术栈选择上,我坚持"用合适的工具解决具体问题"的原则:
- 后端:Django 3.2 + Django REST framework
- 前端:Bootstrap 5 + jQuery
- 数据库:MySQL 8.0
- 部署:Nginx + Gunicorn + Ubuntu 20.04
特别说明:项目完整源码和文档已整理在GitHub仓库,文末会提供获取方式。这个项目完全可用于毕业设计参考,但商业使用需注意遵守相关法律法规。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 核心功能设计与实现
2.1 用户系统设计
用户模块采用Django内置的AbstractUser进行扩展,通过user_type字段区分三种角色:
python复制class User(AbstractUser):
USER_TYPE_CHOICES = (
(1, 'pet_owner'),
(2, 'foster_home'),
(3, 'admin')
)
user_type = models.PositiveSmallIntegerField(choices=USER_TYPE_CHOICES)
phone = models.CharField(max_length=15)
avatar = models.ImageField(upload_to='avatars/')
# 宠物主人专属字段
credit_score = models.IntegerField(default=100)
# 寄养家庭专属字段
address = models.TextField()
certification = models.FileField(upload_to='certs/')
注册流程做了特别优化:
- 基础信息表单(含手机验证)
- 根据用户类型跳转不同完善页面
- 实名认证(对接第三方API)
- 资质审核(仅寄养家庭需要)
踩坑记录:最初想用Django-allauth做第三方登录,但发现微信小程序登录流程太特殊,最终自己实现了OAuth2.0对接。
2.2 宠物档案管理
考虑到宠物信息的专业性,我参考了宠物医院的病历系统设计字段:
python复制class Pet(models.Model):
PET_TYPE = (
('dog', '犬科'),
('cat', '猫科'),
('bird', '鸟类'),
('other', '其他')
)
owner = models.ForeignKey(User, on_delete=models.CASCADE)
name = models.CharField(max_length=50)
pet_type = models.CharField(max_length=10, choices=PET_TYPE)
breed = models.CharField(max_length=50) # 品种
birthday = models.DateField()
weight = models.DecimalField(max_digits=4, decimal_places=1)
is_sterilized = models.BooleanField()
vaccine_records = models.ManyToManyField('Vaccine')
special_notes = models.TextField() # 特殊需求
avatar = models.ImageField(upload_to='pet_avatars/')
疫苗记录单独建表是为了方便生成接种时间提醒:
python复制class Vaccine(models.Model):
name = models.CharField(max_length=50) # 疫苗名称
date_given = models.DateField()
next_due = models.DateField() # 下次接种时间
verified_by = models.CharField(max_length=100) # 验证机构
2.3 订单系统实现
订单状态机是整个系统最复杂的部分,我采用了Django FSM(有限状态机)来管理:
python复制class Order(models.Model):
STATUS = (
('pending', '待确认'),
('confirmed', '已确认'),
('paid', '已支付'),
('ongoing', '服务中'),
('completed', '已完成'),
('cancelled', '已取消')
)
pet = models.ForeignKey(Pet, on_delete=models.PROTECT)
foster_home = models.ForeignKey(User, on_delete=models.PROTECT)
start_date = models.DateField()
end_date = models.DateField()
daily_price = models.DecimalField(max_digits=6, decimal_places=2)
total_amount = models.DecimalField(max_digits=8, decimal_places=2)
status = FSMField(default='pending', choices=STATUS)
@transition(field=status, source='pending', target='confirmed')
def confirm(self):
pass
@transition(field=status, source='confirmed', target='paid')
def pay(self):
# 调用支付接口
pass
# 其他状态转换方法...
支付对接了支付宝沙箱环境,关键代码:
python复制def create_payment(order):
alipay = AliPay(
appid=settings.ALIPAY_APPID,
app_notify_url=settings.ALIPAY_NOTIFY_URL,
app_private_key_string=settings.APP_PRIVATE_KEY,
alipay_public_key_string=settings.ALIPAY_PUBLIC_KEY,
sign_type="RSA2",
debug=True
)
order_string = alipay.api_alipay_trade_page_pay(
out_trade_no=order.order_no,
total_amount=float(order.total_amount),
subject=f"宠物寄养服务-{order.pet.name}",
return_url=settings.ALIPAY_RETURN_URL,
notify_url=settings.ALIPAY_NOTIFY_URL
)
return settings.ALIPAY_GATEWAY + "?" + order_string
3. 关键技术实现细节
3.1 基于GeoDjango的位置服务
寄养家庭搜索依赖地理位置计算,我使用了GeoDjango + PostgreSQL的PostGIS扩展:
- 首先在模型中添加地理字段:
python复制from django.contrib.gis.db import models
class FosterHomeProfile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
location = models.PointField()
service_radius = models.IntegerField() # 服务半径(米)
- 然后实现附近搜索功能:
python复制from django.contrib.gis.geos import Point
from django.contrib.gis.measure import D
def search_nearby(lat, lng, radius=5000):
user_location = Point(float(lng), float(lat), srid=4326)
return FosterHomeProfile.objects.filter(
location__distance_lte=(user_location, D(m=radius))
).distance(user_location).order_by('distance')
- 前端通过浏览器Geolocation API获取用户位置:
javascript复制navigator.geolocation.getCurrentPosition(
(pos) => {
const {latitude, longitude} = pos.coords;
// 调用后端API...
},
(err) => console.error(err),
{enableHighAccuracy: true}
);
3.2 实时消息通知系统
采用Django Channels实现WebSocket通知:
- 配置ASGI应用:
python复制# routing.py
from channels.routing import ProtocolTypeRouter, URLRouter
from channels.auth import AuthMiddlewareStack
import notifications.routing
application = ProtocolTypeRouter({
"http": get_asgi_application(),
"websocket": AuthMiddlewareStack(
URLRouter(
notifications.routing.websocket_urlpatterns
)
),
})
- 消费者实现:
python复制# consumers.py
class NotificationConsumer(AsyncWebsocketConsumer):
async def connect(self):
self.user = self.scope["user"]
self.group_name = f'user_{self.user.id}'
await self.channel_layer.group_add(
self.group_name,
self.channel_name
)
await self.accept()
async def disconnect(self, close_code):
await self.channel_layer.group_discard(
self.group_name,
self.channel_name
)
async def send_notification(self, event):
await self.send(text_data=json.dumps(event["message"]))
- 触发通知示例:
python复制async_to_sync(channel_layer.group_send)(
f'user_{user.id}',
{
'type': 'send_notification',
'message': {
'title': '新订单',
'content': '您有新的寄养请求待确认',
'timestamp': str(timezone.now())
}
}
)
3.3 安全防护措施
- 敏感操作审计日志:
python复制class AuditLog(models.Model):
ACTION_CHOICES = (
('login', '登录'),
('order_create', '创建订单'),
('payment', '支付操作'),
('profile_update', '资料修改')
)
user = models.ForeignKey(User, on_delete=models.SET_NULL, null=True)
action = models.CharField(max_length=20, choices=ACTION_CHOICES)
ip_address = models.GenericIPAddressField()
user_agent = models.TextField()
timestamp = models.DateTimeField(auto_now_add=True)
extra_data = models.JSONField(default=dict)
- 关键接口限流配置:
python复制REST_FRAMEWORK = {
'DEFAULT_THROTTLE_CLASSES': [
'rest_framework.throttling.AnonRateThrottle',
'rest_framework.throttling.UserRateThrottle'
],
'DEFAULT_THROTTLE_RATES': {
'anon': '100/hour',
'user': '1000/hour'
}
}
- 定期安全扫描脚本:
bash复制#!/bin/bash
# 每周日凌晨3点运行
0 3 * * 0 /usr/bin/python manage.py check --deploy
/usr/bin/python manage.py makemigrations --check
/usr/bin/django-admin dbshell --command="SELECT pg_catalog.pg_roles.rolname FROM pg_catalog.pg_roles;" | grep -q "postgres"
4. 部署与性能优化
4.1 生产环境部署
我的部署方案(适合学生项目和小型应用):
-
服务器配置:
- 腾讯云轻量应用服务器
- 2核CPU/4GB内存/80GB SSD
- Ubuntu 20.04 LTS
-
服务架构:
code复制Nginx (80/443) ├── Gunicorn (Django应用) ├── PostgreSQL + PostGIS └── Redis (缓存和Channels后端) -
Nginx关键配置:
nginx复制upstream django_app {
server unix:/run/gunicorn.sock fail_timeout=0;
}
server {
listen 80;
server_name yourdomain.com;
location /static/ {
alias /var/www/pet_foster/static/;
}
location /media/ {
alias /var/www/pet_foster/media/;
}
location / {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://django_app;
}
}
- Gunicorn启动脚本:
bash复制#!/bin/bash
NAME="pet_foster"
DJANGODIR=/var/www/pet_foster
USER=www-data
GROUP=www-data
NUM_WORKERS=3
DJANGO_WSGI_MODULE=config.wsgi
cd $DJANGODIR
source venv/bin/activate
exec gunicorn ${DJANGO_WSGI_MODULE}:application \
--name $NAME \
--workers $NUM_WORKERS \
--user=$USER --group=$GROUP \
--bind=unix:/run/gunicorn.sock \
--log-level=info \
--access-logfile=/var/log/gunicorn/access.log \
--error-logfile=/var/log/gunicorn/error.log
4.2 性能优化实践
-
数据库优化:
- 添加关键字段索引
- 使用select_related/prefetch_related减少查询
- 配置数据库连接池
-
缓存策略:
python复制CACHES = { "default": { "BACKEND": "django_redis.cache.RedisCache", "LOCATION": "redis://127.0.0.1:6379/1", "OPTIONS": { "CLIENT_CLASS": "django_redis.client.DefaultClient", } } } # 视图缓存示例 from django.views.decorators.cache import cache_page @cache_page(60 * 15) def foster_home_list(request): # ... -
异步任务处理:
- 使用Celery处理耗时操作
- 配置flower监控面板
-
前端优化:
- 静态文件CDN加速
- 图片懒加载
- 使用django-compressor压缩资源
5. 项目文档与代码讲解
5.1 项目结构说明
code复制pet_foster/
├── config/ # Django项目配置
├── apps/
│ ├── accounts/ # 用户系统
│ ├── pets/ # 宠物管理
│ ├── orders/ # 订单系统
│ └── notifications/ # 消息通知
├── static/ # 静态文件
├── templates/ # 前端模板
├── requirements/ # 依赖文件
│ ├── base.txt
│ ├── development.txt
│ └── production.txt
├── manage.py
└── README.md # 项目说明
5.2 关键代码讲解
以订单创建为例,展示完整的处理流程:
- 序列化器定义:
python复制class OrderCreateSerializer(serializers.ModelSerializer):
pet_id = serializers.PrimaryKeyRelatedField(
queryset=Pet.objects.all(),
source='pet'
)
foster_home_id = serializers.PrimaryKeyRelatedField(
queryset=User.objects.filter(user_type=2),
source='foster_home'
)
class Meta:
model = Order
fields = ['pet_id', 'foster_home_id', 'start_date', 'end_date']
def validate(self, data):
# 检查日期有效性
if data['start_date'] >= data['end_date']:
raise serializers.ValidationError("结束日期必须晚于开始日期")
# 检查宠物是否属于当前用户
if data['pet'].owner != self.context['request'].user:
raise serializers.ValidationError("无权操作该宠物")
return data
- 视图处理:
python复制class OrderCreateAPIView(CreateAPIView):
serializer_class = OrderCreateSerializer
permission_classes = [IsAuthenticated]
def perform_create(self, serializer):
# 计算价格
foster_home = serializer.validated_data['foster_home']
daily_price = foster_home.fosterhomeprofile.daily_price
days = (serializer.validated_data['end_date'] -
serializer.validated_data['start_date']).days
order = serializer.save(
daily_price=daily_price,
total_amount=daily_price * days,
status='pending'
)
# 发送通知
send_notification.delay(
user_id=foster_home.id,
title='新寄养请求',
message=f"{order.pet.name}的寄养请求待确认"
)
- 信号处理(订单状态变更时):
python复制@receiver(post_save, sender=Order)
def order_status_handler(sender, instance, created, **kwargs):
if not created and 'status' in kwargs.get('update_fields', []):
if instance.status == 'confirmed':
# 生成支付链接
payment_url = create_payment(instance)
send_payment_email.delay(
email=instance.pet.owner.email,
order_id=instance.id,
payment_url=payment_url
)
5.3 开发文档要点
-
环境搭建指南:
- Python 3.8+环境配置
- PostgreSQL安装与PostGIS扩展
- Redis安装配置
- 虚拟环境创建与依赖安装
-
测试数据生成:
python复制def create_test_data(): # 创建测试用户 owner = User.objects.create(username='test_owner', user_type=1) foster = User.objects.create(username='test_foster', user_type=2) # 创建宠物 cat = Pet.objects.create( owner=owner, name='Miao', pet_type='cat', breed='British Shorthair', birthday=date(2020, 5, 1) ) # 创建订单 Order.objects.create( pet=cat, foster_home=foster, start_date=date.today(), end_date=date.today() + timedelta(days=3), daily_price=100, total_amount=300 ) -
API文档示例(使用drf-yasg生成):
python复制class OrderCreateAPIView(CreateAPIView):
"""
post:
创建新的寄养订单
- 参数:
- pet_id: 宠物ID (必填)
- foster_home_id: 寄养家庭用户ID (必填)
- start_date: 开始日期 (YYYY-MM-DD)
- end_date: 结束日期 (YYYY-MM-DD)
- 返回:
- 201: 创建成功
- 400: 参数错误
- 403: 权限不足
"""
# ...视图实现...
6. 常见问题与解决方案
6.1 开发环境问题
Q1: 运行migrate时报错"django.db.utils.OperationalError: could not connect to server"
原因:PostgreSQL服务未启动或连接配置错误
解决方案:
- 检查PostgreSQL服务状态:
sudo service postgresql status - 确认settings.py中的DATABASES配置
- 确保用户有数据库权限:
sudo -u postgres psql -c "GRANT ALL PRIVILEGES ON DATABASE pet_foster TO your_user;"
Q2: 静态文件无法加载
典型表现:页面样式丢失,控制台报404错误
排查步骤:
- 确认DEBUG=False时已运行collectstatic
- 检查Nginx配置中的static路径
- 确认static文件权限:
chmod -R 755 /var/www/pet_foster/static
6.2 业务逻辑问题
Q3: 如何防止用户重复下单同一时间段?
解决方案:在Order模型中添加验证:
python复制class Order(models.Model):
# ...原有字段...
class Meta:
constraints = [
models.UniqueConstraint(
fields=['pet', 'start_date'],
name='unique_booking_per_pet'
),
models.CheckConstraint(
check=Q(start_date__lt=F('end_date')),
name='check_dates_valid'
)
]
def clean(self):
overlapping = Order.objects.filter(
foster_home=self.foster_home,
start_date__lt=self.end_date,
end_date__gt=self.start_date
).exclude(pk=self.pk)
if overlapping.exists():
raise ValidationError("该时间段已被预约")
Q4: 支付成功后如何自动更新订单状态?
处理方案:配置支付宝异步通知接口:
python复制@csrf_exempt
def alipay_notify(request):
data = request.POST.dict()
signature = data.pop("sign")
alipay = get_alipay()
success = alipay.verify(data, signature)
if success and data['trade_status'] == 'TRADE_SUCCESS':
order = Order.objects.get(order_no=data['out_trade_no'])
order.pay()
order.save()
return HttpResponse("success")
return HttpResponse("fail")
6.3 性能问题
Q5: 首页加载缓慢如何优化?
优化方案:
-
添加数据库索引:
python复制class FosterHomeProfile(models.Model): # ...原有字段... class Meta: indexes = [ models.Index(fields=['location']), models.Index(fields=['-rating']) ] -
使用缓存模板片段:
html复制{% load cache %} {% cache 600 foster_home_list %} {% for home in foster_homes %} <!-- 列表项 --> {% endfor %} {% endcache %} -
实现分页加载:
python复制class FosterHomeListView(ListAPIView): queryset = FosterHomeProfile.objects.all() serializer_class = FosterHomeSerializer pagination_class = PageNumberPagination page_size = 10
7. 项目扩展方向
7.1 微信小程序集成
-
接入微信登录:
- 使用django-rest-framework-social-oauth2
- 配置微信开放平台应用
-
小程序API开发:
python复制class WxOrderCreateAPIView(APIView): permission_classes = [IsAuthenticated] def post(self, request): # 验证小程序端数据 # 创建订单 # 返回小程序所需格式 return Response({ 'code': 0, 'data': { 'order_id': order.id, 'payment_params': payment_params } })
7.2 智能推荐系统
基于用户行为的寄养家庭推荐:
-
收集用户行为数据:
python复制class UserBehavior(models.Model): user = models.ForeignKey(User, on_delete=models.CASCADE) item_type = models.CharField(max_length=20) # 'foster_home'/'pet' item_id = models.PositiveIntegerField() behavior = models.CharField(max_length=10) # 'view'/'click'/'order' timestamp = models.DateTimeField(auto_now_add=True) -
实现协同过滤推荐:
python复制def recommend_foster_homes(user): # 获取相似用户 similar_users = get_similar_users(user.id) # 获取推荐列表 homes = FosterHomeProfile.objects.filter( user__in=similar_users ).exclude( user__in=user.blacklist.all() ).order_by('-rating')[:10] return homes
7.3 宠物健康监测
-
对接智能设备API:
python复制class PetHealthData(models.Model): pet = models.ForeignKey(Pet, on_delete=models.CASCADE) device_id = models.CharField(max_length=50) record_time = models.DateTimeField() weight = models.DecimalField(max_digits=5, decimal_places=2) activity = models.IntegerField() # 活动量 temperature = models.DecimalField(max_digits=3, decimal_places=1) -
健康异常检测:
python复制def check_health_abnormal(pet): latest = PetHealthData.objects.filter( pet=pet ).order_by('-record_time').first() if not latest: return False baseline = pet.baseline_health_data return ( abs(latest.weight - baseline.weight) > 0.5 or latest.temperature > 39.5 )
项目完整源码和文档可以通过GitHub获取:github.com/yourusername/pet-foster-platform(此为示例地址,实际使用时请替换为真实地址)。这个项目已经稳定运行半年多,期间根据用户反馈进行了多次迭代。如果用于毕业设计,建议在以下方向进行扩展:
- 增加宠物保险模块
- 实现智能合约保障资金安全
- 开发宠物行为分析功能
- 接入更多第三方服务(如宠物医院)
开发过程中最大的体会是:业务逻辑的严谨性比技术炫技更重要。比如订单状态机的设计,我们迭代了5个版本才最终确定所有状态转换规则。另外,与支付、地图等第三方服务的对接要特别注意异常处理和日志记录。
