Django+Vue.js租房推荐系统实战:协同过滤与大屏可视化全解析
2026/9/23 4:05:23 网站建设 项目流程

1. 项目核心思路与整体拆解

做毕业设计最怕什么?不是不会写代码,而是选了个满大街都是的题目,开题报告写得费劲,答辩时老师一眼看穿没有技术含量。“Django+Vue.js租房推荐系统”这类题目,表面看是拼装了一个前后端分离的Web应用,但仔细拆解,它把推荐算法、数据可视化、大数据分析三个高价值标签全占了,而且每个模块都能独立展开深挖,这正是答辩时最能加分的地方。

1.1 核心需求解析:毕设选题为什么是它

租房信息平台本身并不新鲜,市面上贝壳、自如、链家早就做透了。但如果把视角从“一个租房网站”切换到“一个完整的推荐系统”,思路就完全不一样了。

这个题目的第一层价值,在于它天然具备“用户-房源”双端数据。用户有点击、收藏、预约看房行为,房源有户型、租金、位置、配套设施属性。基于这些数据,我们可以做基于协同过滤的个性化推荐,也可以做基于内容的属性匹配推荐,甚至可以把两者做成混合推荐来提升精度。这些内容往论文里一放,“基于用户行为的个性化租房推荐研究”这个研究方向,比单纯写个增删改查的毕设有说服力得多。

第二层价值,在于“大屏可视化”这个点。大数据这个标签在毕业设计里含金量很高,但很多同学不知道落地到什么地方。“租房大屏可视化”是一个非常好的载体:把房源价格分布、区域热度、户型需求比、租金走势用大屏形式呈现出来,既有视觉冲击力,又有数据价值。而且现在很多高校的毕设要求里都有“数据可视化”这个指标,大屏是最容易出效果的部分。

第三层价值在于技术栈覆盖率。Django负责后端、ORM模型、JWT认证、接口开发;Vue.js负责前端SPA页面、组件化开发、状态管理、ECharts图表交互;Redis做热门房源的缓存和点击行为队列;MySQL做业务数据持久化;推荐算法模块可以用协同过滤也可以用简单规则。这一套组合拳打下来,技术栈的广度是够的,每个点都能在论文里单独开一个章节去写。

1.2 系统架构与核心功能地图

整个系统从前到后可以拆成四层:

  • 数据层:MySQL存储用户信息、房源信息、收藏记录、浏览历史;Redis缓存热门房源和用户实时行为。
  • 后端服务层:Django + Django REST Framework提供RESTful API,包含用户模块、房源模块、推荐模块、统计模块;推荐模块基于用户的协同过滤算法,实时计算相似用户和推荐列表。
  • 前端应用层:Vue.js单页应用,页面分为C端用户端(浏览、搜索、收藏、推荐)和可视化大屏端(数据总览、价格走势、区域热度、户型分布)。
  • 部署运维层:开发环境用前后端分离模式,后端跑Django自带的开发服务器,前端用Vite或WebpackDevServer代理;生产环境Nginx托管前端静态文件并反向代理后端的API请求。

具体到功能模块,我建议至少覆盖这几个核心闭环:用户注册和登录是必须有的;房源浏览与条件筛选(区域、户型、租金范围、朝向)是基础;收藏和取消收藏用于积累用户行为数据;基于收藏和浏览记录生成推荐列表是核心卖点;管理后台做房源的增删改查;大屏可视化作为独立页面展示统计数据。

这里要说一个我在初期踩过的坑:千万不要把“推荐系统”只做成一个摆设按钮。很多同学的毕设,推荐列表是后端随机出的假数据,虽然答辩时能混过去,但经不起追问。建议至少让协同过滤算法真正跑起来,哪怕数据量不大,逻辑完整了,老师问起来你也能挺直腰杆。

2. 环境准备与项目初始化

这套系统虽然技术栈多,但环境搭建并不复杂。我建议开发环境统一用Python 3.10以上版本和Node.js 16以上版本,尽量别用太老的版本——新版本不是追求新鲜,主要是Django 4.x和Vue 3都已经非常稳定,并且相关的第三方库兼容性也做得更好了。

2.1 后端Django项目搭建

新建一个独立的虚拟环境是必须的第一步,前后端依赖放一起后面一定会出问题。我习惯用venv,命令也简单:

mkdir rental_recommend cd rental_recommend python -m venv venv # Windows激活 venv\Scripts\activate # macOS/Linux激活 source venv/bin/activate

激活虚拟环境后,安装核心依赖。Django版本我推荐4.2 LTS版,配合Django REST Framework做接口开发,django-cors-headers解决跨域,djangorestframework-simplejwt做基于JWT的登录认证,Redis连接统一用django-redis。

pip install django==4.2.* pip install djangorestframework pip install django-cors-headers pip install djangorestframework-simplejwt pip install django-redis pip install pandas numpy

创建Django项目和应用。项目名我习惯叫rental_backend,应用按模块拆:users管理用户,houses管理房源,recs做推荐,stats做统计,连管理后台都省得重新写。

django-admin startproject rental_backend cd rental_backend python manage.py startapp users python manage.py startapp houses python manage.py startapp recs python manage.py startapp stats

在settings.py中把应用注册进去,再配置好数据库连接。MySQL比SQLite好在能扛更大的数据量,毕业后你如果还想往简历上放,MySQL经验也算加分项。

DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'rental_db', 'USER': 'root', 'PASSWORD': '你的密码', 'HOST': '127.0.0.1', 'PORT': '3306', 'OPTIONS': {'charset': 'utf8mb4'}, } }

再在settings.py里把REST_FRAMEWORK和SIMPLE_JWT的配置补上,身份认证用JWT,权限默认为AllowAny,之后在需要登录的接口上单独加IsAuthenticated权限类。跨域这块,把CORS_ALLOW_ALL_ORIGINS设为True在开发阶段最省事,部署到生产环境再收紧。

2.2 前端Vue.js项目搭建

前端我用Vite搭建Vue 3项目,相比Vue CLI,Vite启动速度明显更快,开发体验也更好,现在绝大多数教程和团队都切过来了,用旧版反而容易踩坑。

npm create vite@latest rental_front -- --template vue cd rental_front npm install npm install vue-router@4 axios element-plus echarts

这里顺便解释一下为什么选Element Plus而不是别的UI库。租房系统涉及大量的列表、表单、标签、轮播图,Element Plus组件全覆盖,后端管理页面可以直接用el-table、el-form、el-dialog快速搭出来,对毕设开发效率提升非常明显。ECharts则是做大屏可视化的事实标准,地图、折线图、饼图都支持得非常好。

启动开发服务器后,Vite默认跑在5173端口,Django跑在8000端口,跨域就产生了。前面在Django里配置django-cors-headers,就是为了让浏览器允许这两个端口之间互相通信。开发阶段我还习惯在vite.config.js里配一个代理,把/api开头的请求转发到后端,这样前端代码里就用相对路径请求,部署到服务器上不用改代码。

server: { port: 5173, proxy: { '/api': { target: 'http://127.0.0.1:8000', changeOrigin: true } } }

2.3 数据模型设计:从业务出发的表结构

数据模型是后端的灵魂,表结构设计好了,后面写接口和推荐算法都会顺畅很多。我们至少需要四张核心表:用户表、房源表、收藏记录表、浏览记录表。

用户表可以直接用Django自带的User模型扩展,添加一个手机号字段、头像字段和用户类型字段。房源表字段比较多,包括标题、描述、户型(几室几厅)、面积、朝向、楼层、租金、押金、所在区域、详细地址、经纬度坐标、配套设施(用JSON格式存储,比如地铁、电梯、阳台)、房屋图片(存多个URL)、是否已出租、发布时间等。收藏记录表关联用户和房源,外加一个收藏时间。浏览记录表关联用户和房源,记录浏览时间。

这样设计之后,推荐算法所需的数据源就齐了。用户的行为数据(浏览、收藏)是协同过滤的输入,房源属性数据是内容推荐的基础。统计模块则可以直接用Django ORM做聚合查询,比如统计每个区域的房源数量、平均租金、户型占比等。

3. 推荐模块的核心实现

推荐系统是这个毕设真正的灵魂,也是最容易在答辩时被追问的模块。我采用的方案是经典的基于用户的协同过滤,再加上一个基于内容的冷启动策略做兜底,这样既保证算法可解释,又不会因为数据稀疏导致推荐列表为空。

3.1 协同过滤算法原理与实现步骤

基于用户的协同过滤核心思想是:如果用户A和用户B在过去的收藏/浏览行为上高度相似,那么A喜欢的房源,B大概率也会喜欢。算法分三步骤:

第一步,构建用户-房源行为矩阵。行是用户,列是房源,值可以是是否收藏(0/1),也可以是浏览次数的加权分数。我建议简单一点,收藏记1分,浏览记0.5分,这样不同行为可以加权累加。

第二步,计算用户之间的相似度。可以通过余弦相似度:两个用户的向量点积,除以两个向量模长的乘积。Django里用Python就能实现,不需要额外依赖。但要注意,当用户量比较大(上万级别)时,需要转换成矩阵运算,这时numpy或者pandas会更高效。

第三步,为目标用户推荐。找出与当前用户最相似的K个邻居,把这K个邻居收藏过但当前用户没收藏过的房源汇总,按相似度加权后的分数从高到低排序,取前N条作为推荐结果。

这里给一个简化的实现示例(基于pandas):

import pandas as pd import numpy as np def build_user_item_matrix(records): df = pd.DataFrame(records, columns=['user_id', 'house_id', 'score']) matrix = df.pivot_table(index='user_id', columns='house_id', values='score', fill_value=0) return matrix def cosine_similarity(matrix): norm = np.linalg.norm(matrix, axis=1, keepdims=True) matrix_norm = matrix / np.where(norm == 0, 1, norm) return np.dot(matrix_norm, matrix_norm.T) def recommend_for_user(user_id, matrix, sim_matrix, k=5, top_n=10): user_idx = list(matrix.index).index(user_id) sim_scores = sim_matrix[user_idx] similar_users = np.argsort(sim_scores)[::-1][1:k+1] # 聚合邻居收藏过的房源,排除当前用户已收藏的 ... return top_house_ids

3.2 冷启动问题与内容推荐兜底方案

协同过滤有个典型问题:新用户没有行为数据,算什么相似度?新房源没有用户收藏过,怎么被推荐?这就是冷启动。

针对用户冷启动,我用基于内容的推荐做兜底。新用户注册后,可以补充一个偏好问卷(可跳过),选择意向区域、预算区间、偏好户型。推荐模块直接按这些偏好筛选房源,返回前N条。如果用户连问卷都跳过了,那就按热度推荐,也就是按浏览量、收藏量加权排序,或者按最新发布排序。

针对房源冷启动,关键是不要让它永远沉没。我是这样处理的:在推荐结果里加入“新鲜度”因子,在其它得分相同的条件下,最近发布的房源排前面。同时,后台管理可以在推荐模块里配置一个“人工置顶”功能,把新录入手动的房源推到推荐流,保证它有曝光机会。

这里要强调一个经验:无论你用什么算法,推荐列表在返回给前端时,一定要记录下这次推荐的结果和当时的用户行为数据。

3.3 行为数据采集与异步化处理

光有算法不够,还要让数据源源不断地流进来。我可以直接在视图层埋点:用户浏览房源详情时,前端调用一个记录浏览记录的接口;用户点击收藏时,调用收藏接口,同时把行为ID写入Redis的队列里。后端异步任务再从Redis队列取数据,写入MySQL。

为什么绕一圈用Redis而不是直接写MySQL?因为浏览行为是高频操作,如果每个请求都去数据库执行INSERT,高并发下数据库压力大,而且也会拖慢接口响应。用Redis做消息缓冲,先快速写入内存,再异步批量落库,这是生产环境的标准做法。Node里可以用celery这类异步任务队列,但毕设里我尽量简化——直接用Django的channels或一个简单的threading定时任务也能做,只要把落库刷盘逻辑写清楚就行。

还有一个细节:用户的行为数据表不需要保存太久。在真实场景里,三个月以前的行为对推荐的意义不大,而且表越来越大影响查询性能。我们在毕业设计中也可以通过定时任务,定期清理三个月以上的浏览记录,这样既控制了数据规模,也符合实际情况。

4. 可视化大屏的设计与实现

大屏可视化是给评委第一印象加分的关键模块。一张布局工整、配色统一的大屏,让系统“大数据”的标签瞬间立住了。

4.1 大屏数据接口与统计设计

大屏不能是静态假数据,必须从后端统计接口实时拉取。我建议至少准备四个核心统计接口:

  • 总览指标:总房源数、总用户数、今日新增房源、今日新增用户、整体出租率。
  • 区域热度分析:按区域分组统计房源数量、平均租金、出租率,返回列表供地图或柱状图展示。
  • 租金走势:按月份统计租金中位数和平均值,观察价格变化趋势。
  • 户型分布:按户型(一室/两室/三室/四室及以上)统计房源数量占比。

后端用Django ORM就能完成聚合查询:

from django.db.models import Count, Avg from houses.models import House def region_stats(request): data = ( House.objects .values('district') .annotate(count=Count('id'), avg_price=Avg('rent_price')) .order_by('-count') ) return JsonResponse(list(data), safe=False)

为了让大屏看起来更“实时”,可以在前端设置定时轮询,比如每30秒请求一次接口,更新图表数据;如果后续有条件,可以改造为WebSocket推送。但毕设用轮询完全够用,而且代码好写,不引入额外复杂度。

4.2 ECharts核心图表配置与实时刷新

大屏页面我用的是深色科技风。背景是深蓝色渐变,辅以霓虹色系(青色、橙色)作为图表主题色。具体实现上,ECharts支持自定义主题,可以把颜色配置提取成公共对象统一管理。

以区域房源地图为例,大屏中央放一个全国地图(或城市地图),区域上用不同颜色的散点表示房源密度,点击某个区域还能下钻展示该区域的细部信息。ECharts官方提供了地图注册方法,只要准备好GeoJSON数据,就能快速集成:

import * as echarts from 'echarts' import geoJson from '@/assets/china.json' echarts.registerMap('china', geoJson) const chart = echarts.init(document.getElementById('map')) chart.setOption({ series: [{ type: 'map', map: 'china', roam: true, label: { show: false }, itemStyle: { areaColor: '#1a2b4a', borderColor: '#3a6ea5' }, emphasis: { label: { show: true }, itemStyle: { areaColor: '#2f89cf' } } }] })

底部放租金趋势折线图和户型占比饼图,用ECharts的Grid布局排列。轮询刷新我这里直接封装成一个工具方法:

function startPolling(url, callback, interval = 30000) { const fetchData = async () => { const res = await axios.get(url) callback(res.data) } fetchData() const timer = setInterval(fetchData, interval) return () => clearInterval(timer) }

4.3 大屏适配与前端工程化

做可视化大屏,一个容易被忽略但极其影响观感的细节是屏幕分辨率适配。不同分辨率的屏幕下(1920×1080、2560×1440、甚至4K),图表大小必须自适应。我用一套非常成熟的做法:按1920×1080设计稿开发,外层容器设置固定宽高,然后通过transform: scale()做整体缩放。

大致逻辑是:

function screenAdapter() { const designWidth = 1920 const designHeight = 1080 const scaleX = window.innerWidth / designWidth const scaleY = window.innerHeight / designHeight const scale = Math.min(scaleX, scaleY) document.getElementById('screen').style.transform = `scale(${scale})` } window.addEventListener('resize', screenAdapter)

为什么用缩放而不是百分比布局?因为固定设计稿能够保证图表内字体、间距在视觉上绝对统一,不会因为屏幕比例不同导致布局错乱。这是大屏项目的通用做法,实测在投影和显示器上都表现良好。

4.4 大屏页面与后端接口的联调优化

前后端联调时,最容易出现的问题是大屏页面在加载时,多个图表并发请求后端,导致后端压力过大或者响应变慢。我的优化方案是两板斧:

第一板斧,后端接口做Redis缓存。像区域统计、租金走势这类数据,变动频率并不高,完全可以缓存5分钟,减少数据库压力:

from django.core.cache import cache def region_stats(request): data = cache.get('region_stats') if data is None: data = list(House.objects.values('district').annotate(...)) cache.set('region_stats', data, timeout=300) return JsonResponse(data, safe=False)

第二板斧,前端控制请求时序。首屏先请求最核心的总览指标和区域数据,等这两个渲染出来了,再去请求租金走势和户型占比。避免4个图表同时发请求,给用户一种瞬间加载完成的感觉。

5. 常见问题与排查技巧实录

在开发这个项目的过程中,我从环境配置到部署上线踩了不止一个坑,这里整理几个最常见的问题和排查方法,希望能帮大家少走弯路。

5.1 跨域请求失败,接口502/403

前端开发服务器在5173端口,后端在8000端口,浏览器默认阻止跨域请求。解决方式我在第二章节提到了配置CORS中间件,但还有两个细节需要注意:第一,django-cors-headers必须放在MIDDLEWARE列表尽量靠上的位置,最好在CommonMiddleware之前,否则可能部分请求不生效;第二,如果你用了JWT认证,前端请求时必须在Authorization头里带上Bearer token,否则接口返回401,非常容易误判为跨域问题。

5.2 图片上传/显示404,静态文件丢失

租房房源图片很多,前端有时显示404。这个问题多半出在Django的静态文件处理和MEDIA路径配置上。在settings.py里,要保证:

MEDIA_URL = '/media/' MEDIA_ROOT = BASE_DIR / 'media'

然后在主工程urls.py里配好:

from django.conf import settings from django.conf.urls.static import static urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

开发环境这样配就没问题了。生产部署用Nginx托管/media路径指向本地的media目录。

5.3 推荐接口响应慢,从1秒优化到200毫秒以内

我的推荐接口起初很慢,排查发现每次请求都重新计算了一遍协同过滤矩阵——在数据量小的时候还行,数据量稍大就延迟明显。优化思路是:

  • 把用户相似度矩阵缓存到Redis,每20分钟更新一次(行为数据变化后重算)。
  • 当前用户的推荐列表也缓存10分钟。
  • 把向量计算用numpy重写,代替纯Python循环。

这一套下来,接口耗时从900毫秒降到了200毫秒以内,效果立竿见影。毕设在答辩演示时,流畅的响应速度也是一个隐形的加分项。

5.4 Redis未启动导致登录接口直接白屏

很多同学会在本地开发时忘记启动Redis服务,结果前端点击登录后,后端直接抛异常或者卡住。排查思路很简单:首先在浏览器DevTools里看Network标签,确认请求是否发出;再看后端的命令行输出,有Exception说明后端崩了;如果是Redis连接超时的报错,启动Redis服务即可——Windows下可以用redis-server启动本机服务;macOS/Linux则用redis-serversudo systemctl start redis

5.5 前端页面样式异常,Vue组件加载不出来

如果Vue页面加载后一片空白,大概率是组件导入路径写错,或者是Vue Router配置有问题。先在控制台看有没有大量404的JS请求,再检查路由的history模式是否需要服务器支持。开发环境用createWebHashHistory()最省心,部署到Nginx再用createWebHistory()并配置好try_files回退。

另外大屏页面的transform: scale()容器,有时会跑出视口,记得给最外层加overflow: hidden

6. 部署上线与毕设答辩加分项

毕业设计写代码是基础,把它包装好、讲清楚,才是拿高分的关键。部署方案我推荐Nginx + uWSGI(或Waitress)在服务器上跑,但毕设如果只需要本地演示,也可以简化成前后端分离但都跑在一台机器上的方案。

6.1 生产环境部署方案与步骤

第一步,前端构建。在rental_front目录下执行npm run build,生成dist目录。Nginx的根目录指向dist,同时配置location /api反向代理到Django后端接口。

第二步,后端部署。我自己的经验是,如果服务器是Windows,可以直接用waitress代替uWSGI,Windows中央管理的支持不友好:

pip install waitress waitress-serve --port=8000 rental_backend.wsgi:application

如果是Linux服务器,uWSGI或Gunicorn二选一。启动命令和配置方式网上很多,我这里不再赘述,但要强调Gunicorn的进程数不要贪多,一般CPU核心数加1就够了。

第三步,数据库配置好MySQL,初始化好数据表,然后创建管理员账户。在settings.py里把DEBUG设为False,配置好ALLOWED_HOSTS,把后端的SECRET_KEY换成新的随机值。

6.2 答辩演示准备工作:如何让系统在5分钟内讲清楚

答辩演示是整个毕设的临门一脚。我的建议是,事前准备好以下几条演示路径:

  • 从用户注册登录讲起,展示前后端分离的架构,说清楚JWT认证流程。
  • 演示用户浏览房源、收藏房源,尽量多制造一些“行为数据”。
  • 展示推荐列表,切换几个不同偏好的用户,让推荐结果有明显差异。
  • 打开大屏可视化页面,讲解统计数据是怎么来的,每个图表对应后端哪个接口。
  • 有准备地讲讲冷启动、缓存优化和异步落库,这三个点马上能拉开与普通毕设的差距。

把系统的亮点放到前面讲,让老师迅速感受到工作量和技术含量,后面的提问环节你也能游刃有余。

6.3 经验心得:这套架构还能往哪儿扩展

系统做完后,我把它扩展成了一个小型的数据分析平台:把用户行为数据导出成CSV,用pandas做基础分析,再用上次讲的K-means聚类,把用户按照租房偏好分成几类人群,然后基于人群特征做差异化推荐。这样一下子就把“大数据”这个词落到了实处,而不是停留在口号上。

如果你时间充裕,也可以把Spark接进来做离线的推荐计算,或者把前端改成小程序版本。但说实话,对于本科毕业设计来说,Django+Vue.js+协同过滤+可视化大屏这套组合已经足够扎实了,把现有模块做精做深,远比再铺一个新功能更划算。

我自己带过好几个师弟师妹做类似的选题,最大的共性问题不是技术不会,而是文档和代码对不上。所以我的最后一个建议:每完成一个模块,立刻截图、记录笔记,并同步更新开题报告和论文——等到最后集中写文档,那你一定会后悔。这个项目做下来,代码量不算大,但逻辑链条很长,靠临时记忆很难完整复盘。养成边写代码边沉淀文档的习惯,你会发现后面的毕业论文写得异常顺溜。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询