ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

校园O2O点评系统开发:Python+Django+Vue实战

校园O2O点评系统开发:Python+Django+Vue实战 1. 项目概述与核心价值校园商家消费点评系统是一个典型的O2OOnline to Offline平台应用它解决了校园场景下学生与商家之间的信息不对称问题。这个基于Python后端Vue前端的技术栈组合实际上构建了一个轻量版的校园大众点评。我在实际开发中发现这类系统最核心的价值在于三点为学生提供真实的消费决策参考避免踩雷帮助优质商家获得更多曝光尤其适合校园内新开店铺沉淀校园消费大数据后续可做热门品类分析2. 技术架构设计2.1 整体技术选型采用前后端分离架构后端Python Django REST Framework前端Vue 3 Element Plus数据库MySQL 8.0关系型 Redis缓存部署Nginx Docker选择PythonDjango的原因开发效率高适合快速迭代的校园项目DRF框架完美支持RESTful API开发丰富的第三方库支持如爬虫、数据分析2.2 数据库设计要点核心表结构设计class Shop(models.Model): name models.CharField(max_length100) category models.CharField(max_length50) # 餐饮/文具/快递等 location models.CharField(max_length200) opening_hours models.JSONField() # 存储复杂时间结构 class Review(models.Model): user models.ForeignKey(User, on_deletemodels.CASCADE) shop models.ForeignKey(Shop, on_deletemodels.CASCADE) rating models.SmallIntegerField(validators[MinValueValidator(1), MaxValueValidator(5)]) content models.TextField() photos models.JSONField() # 存储图片URL数组 created_at models.DateTimeField(auto_now_addTrue)注意校园场景要特别处理高频访问数据比如食堂窗口的实时评分应该用Redis缓存避免频繁查库。3. 核心功能实现3.1 商家详情页开发Vue前端关键代码template div classshop-container el-rate v-modelshop.avg_rating disabled show-score :colors[#99A9BF, #F7BA2A, #FF9900] /el-rate el-tabs v-modelactiveTab el-tab-pane label基本信息 nameinfo shop-info :datashop/ /el-tab-pane el-tab-pane label评价 namereviews review-list :reviewsreviews load-morehandleLoadMore/ /el-tab-pane /el-tabs /div /template后端API接口示例api_view([GET]) def shop_detail(request, shop_id): shop get_object_or_404(Shop, pkshop_id) reviews Review.objects.filter(shopshop).order_by(-created_at)[:10] # 计算平均分时使用缓存 cache_key fshop_rating_{shop_id} avg_rating cache.get(cache_key) if avg_rating is None: avg_rating shop.review_set.aggregate(Avg(rating))[rating__avg] or 0 cache.set(cache_key, avg_rating, 60*15) # 缓存15分钟 serializer ShopDetailSerializer({ shop: shop, reviews: reviews, avg_rating: round(avg_rating, 1) }) return Response(serializer.data)3.2 评价排序算法校园场景的特殊需求新评价权重更高反映近期质量变化长篇评价给予额外权重实名认证学生的评价更可信实现代码def get_review_score(review): # 基础分 score review.rating * 20 # 新鲜度加分最近7天内 if (timezone.now() - review.created_at).days 7: score 15 # 内容长度加分 content_length len(review.content.strip()) if content_length 100: score min(content_length//10, 30) # 每10字加1分上限30 # 认证用户加分 if review.user.is_verified: score 20 return score4. 校园特色功能实现4.1 课表关联推荐通过对接学校教务系统API需学生授权实现根据下一节课的教学楼位置推荐附近商家根据课间时间长短过滤推荐如只有10分钟课间就不推荐需要排队的商家def get_nearby_shops(building, time_available): queryset Shop.objects.filter( location__startswithbuilding, estimated_wait_time__ltetime_available-3 # 预留3分钟步行时间 ).order_by(-avg_rating)[:5] # 特殊逻辑上午时段优先推荐早餐类 if 8 datetime.now().hour 10: queryset queryset.filter(category早餐) return queryset4.2 校园卡支付集成与学校一卡通系统对接的关键点使用学校提供的Java SDK需要用Py4J桥接交易流水号必须符合学校规范每日对账机制支付流程伪代码def campus_card_payment(user, shop, amount): # 生成符合规范的订单号 order_id f{datetime.now():%Y%m%d}{user.stu_id[-4:]}{random.randint(1000,9999)} # 调用Java SDK result jpype.JClass(CampusPaySDK).transfer( user.card_id, shop.merchant_code, amount, order_id ) if result.getStatus() SUCCESS: create_payment_record(user, shop, amount, order_id) return True raise PaymentError(result.getErrorMessage())5. 性能优化实践5.1 图片处理方案校园场景的特殊需求学生上传的菜品图片需要压缩但保留可识别度支持EXIF方向自动校正使用Pillow进行智能压缩def process_upload_image(image): try: img Image.open(image) # 自动旋转 if hasattr(img, _getexif): exif img._getexif() if exif: orientation exif.get(0x0112) if orientation 3: img img.rotate(180, expandTrue) elif orientation 6: img img.rotate(270, expandTrue) elif orientation 8: img img.rotate(90, expandTrue) # 智能压缩 if img.height 800 or img.width 800: output_size (800, 800) img.thumbnail(output_size, Image.Resampling.LANCZOS) # 转换为WebP格式 buffer BytesIO() img.save(buffer, formatWEBP, quality85) return buffer.getvalue() except Exception as e: logger.error(fImage process error: {str(e)}) raise5.2 缓存策略设计采用多级缓存方案热点数据Redis缓存商家基础信息本地内存缓存校区配置等不变数据CDN缓存静态资源Django缓存配置示例CACHES { default: { BACKEND: django_redis.cache.RedisCache, LOCATION: redis://127.0.0.1:6379/1, OPTIONS: { CLIENT_CLASS: django_redis.client.DefaultClient, SOCKET_CONNECT_TIMEOUT: 5, # 秒 SOCKET_TIMEOUT: 5, } }, local: { BACKEND: django.core.cache.backends.locmem.LocMemCache, LOCATION: unique-snowflake, } }6. 安全防护措施6.1 防刷评机制校园场景常见问题商家找人刷好评恶意用户刷差评防护方案基于行为的检测def is_suspicious_review(user): # 同一用户短时间内多次评价 recent_count Review.objects.filter( useruser, created_at__gtetimezone.now()-timedelta(hours1) ).count() if recent_count 3: return True # 评价内容相似度检测 last_reviews Review.objects.filter(useruser).order_by(-id)[:5] if len(last_reviews) 3: similarity calculate_text_similarity( [r.content for r in last_reviews] ) if similarity 0.7: return True return False基于设备的指纹识别前端实现import FingerprintJS from fingerprintjs/fingerprintjs async function getDeviceId() { const fp await FingerprintJS.load() const result await fp.get() return result.visitorId }6.2 敏感内容过滤校园场景需要特别关注不当言论个人隐私信息实现方案class ContentFilter: def __init__(self): self.keywords self._load_keywords() self.regex_patterns [ r\d{11}, # 手机号 r\d{17}[\dXx], # 身份证号 r\d{4}-\d{2}-\d{2} # 生日 ] def check_text(self, text): # 关键词匹配 for kw in self.keywords: if kw in text: return False # 正则匹配 for pattern in self.regex_patterns: if re.search(pattern, text): return False return True7. 部署与运维实践7.1 Docker化部署校园服务器通常配置有限推荐使用Docker Composedocker-compose.yml示例version: 3.8 services: web: build: . ports: - 8000:8000 volumes: - ./static:/app/static env_file: - .env depends_on: - redis - db db: image: mysql:8.0 environment: MYSQL_ROOT_PASSWORD: ${DB_PASSWORD} MYSQL_DATABASE: campus_review volumes: - mysql_data:/var/lib/mysql redis: image: redis:6-alpine ports: - 6379:6379 volumes: mysql_data:7.2 日志收集方案校园IT部门通常需要运维日志推荐配置LOGGING { version: 1, handlers: { file: { level: INFO, class: logging.handlers.TimedRotatingFileHandler, filename: /var/log/campus_review/app.log, when: midnight, backupCount: 7, }, console: { level: DEBUG, class: logging.StreamHandler, }, }, loggers: { django: { handlers: [file, console], level: INFO, }, }, }8. 项目演进建议在实际运营中我们发现以下几个优化方向值得关注季节性运营策略开学季重点推广教材、文具类商家考试周增加自习室、咖啡厅曝光毕业季推出纪念品商家专题数据价值挖掘def analyze_consumption_trends(): # 分析各食堂窗口客流时段分布 df pd.DataFrame.from_records( Review.objects.filter(shop__category食堂) .values(shop__name, created_at__hour) .annotate(countCount(id)) ) # 生成热力图数据 heatmap_data df.pivot_table( indexshop__name, columnscreated_at__hour, valuescount, fill_value0 ) return heatmap_data.to_dict()硬件扩展可能食堂档口加装IoT设备自动获取排队人数与校园POS机对接获取实时交易数据教室门口屏幕显示附近商家推荐
返回列表