1. 项目背景与核心需求
武城市作为新兴的二线城市,近年来人口流入量持续增加,租房市场需求旺盛。但传统的中介管理模式存在信息不透明、管理效率低下等问题。这个毕业设计项目正是为了解决这一痛点——通过Python技术栈构建一个轻量级但功能完备的租房管理系统。
我在实际开发中发现,这类系统需要同时满足三类用户的核心诉求:
- 租客:快速找到符合预算、地段、房型要求的房源
- 房东:便捷发布房源、管理租约和收付款
- 管理员:审核信息、处理投诉、维护平台秩序
系统采用B/S架构,前端使用Vue.js+ElementUI实现响应式界面,后端采用Django REST Framework构建API服务,数据库选用MySQL 8.0。这种技术组合既保证了开发效率,又能满足毕业设计对技术深度的要求。
提示:选择Django而非Flask的主要考虑是其自带Admin后台,可以快速实现房源审核等管理功能,这对毕设演示非常有利。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 系统架构设计详解
2.1 技术栈选型分析
后端选择Python+Django的组合主要基于以下考量:
- Django的ORM能大幅简化数据库操作,比如房源查询可以通过
House.objects.filter(price__lte=max_price)这样的链式调用实现 - Django REST Framework提供完善的序列化和权限控制,例如用
@permission_classes([IsAuthenticated])装饰器保护敏感接口 - 内置的Admin界面节省开发时间,通过简单配置即可生成房源管理后台
前端采用Vue 3的组合式API写法,典型代码结构如下:
javascript复制// 房源搜索组件
const searchParams = reactive({
district: '',
minPrice: null,
maxPrice: null
})
const searchResults = ref([])
const handleSearch = async () => {
const { data } = await axios.get('/api/houses/', { params: searchParams })
searchResults.value = data
}
2.2 数据库设计关键点
ER图中需要重点设计以下几个实体关系:
- 用户-房源:一对多关系(一个房东拥有多套房源)
- 房源-合同:一对一关系(每份合同对应唯一房源)
- 用户-合同:多对多关系(租客和房东通过合同关联)
建表示例:
sql复制CREATE TABLE `house` (
`id` int NOT NULL AUTO_INCREMENT,
`title` varchar(100) NOT NULL,
`address` varchar(200) NOT NULL,
`area` decimal(10,2) NOT NULL,
`price` decimal(10,2) NOT NULL,
`landlord_id` int NOT NULL,
`status` enum('available','rented','hidden') DEFAULT 'available',
PRIMARY KEY (`id`),
FOREIGN KEY (`landlord_id`) REFERENCES `user` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
3. 核心功能实现细节
3.1 智能房源推荐算法
在搜索功能中,我们实现了基于用户行为的推荐逻辑:
- 记录用户的搜索关键词和点击行为
- 使用协同过滤算法计算相似用户
- 推荐相似用户感兴趣的房源
核心Python代码:
python复制def recommend_houses(user_id):
# 获取用户历史行为
history = UserBehavior.objects.filter(user_id=user_id).values_list('house_id', flat=True)
# 找到相似用户(简化版示例)
similar_users = UserBehavior.objects.exclude(user_id=user_id) \
.filter(house_id__in=history) \
.values('user_id') \
.annotate(count=Count('user_id')) \
.order_by('-count')[:5]
# 获取推荐房源
recommended = House.objects.filter(
id__in=UserBehavior.objects.filter(
user_id__in=[u['user_id'] for u in similar_users]
).values_list('house_id', flat=True)
).exclude(id__in=history)
return recommended
3.2 在线签约与支付流程
签约流程采用状态机模式设计:
python复制class Contract(models.Model):
STATES = [
('draft', '草稿'),
('pending', '待签署'),
('signed', '已签署'),
('paid', '已支付'),
('canceled', '已取消')
]
state = models.CharField(max_length=20, choices=STATES, default='draft')
def sign(self, user):
if self.state != 'pending':
raise InvalidStateError("合同当前状态不可签署")
if user not in [self.landlord, self.tenant]:
raise PermissionError("无权签署此合同")
if user == self.landlord:
self.landlord_signed = True
else:
self.tenant_signed = True
if self.landlord_signed and self.tenant_signed:
self.state = 'signed'
self.save()
支付接口对接了支付宝沙箱环境:
python复制def create_payment(contract_id):
contract = Contract.objects.get(id=contract_id)
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=f"CT{contract.id}",
total_amount=str(contract.total_amount),
subject=f"{contract.house.title} 租金支付",
return_url=settings.ALIPAY_RETURN_URL,
notify_url=settings.ALIPAY_NOTIFY_URL
)
return settings.ALIPAY_GATEWAY + "?" + order_string
4. 开发中的典型问题与解决方案
4.1 并发导致的房源状态冲突
当多个用户同时预订同一套房源时,会出现超卖问题。我们通过Django的select_for_update实现行级锁:
python复制def reserve_house(house_id, user):
with transaction.atomic():
house = House.objects.select_for_update().get(id=house_id)
if house.status != 'available':
raise ConflictError("房源已被预订")
house.status = 'reserved'
house.save()
Contract.objects.create(
house=house,
tenant=user,
landlord=house.landlord,
start_date=timezone.now().date(),
end_date=timezone.now().date() + timedelta(days=365),
monthly_rent=house.price
)
4.2 地理空间查询优化
为了实现"附近房源"功能,我们使用MySQL的空间扩展:
sql复制-- 先为房源表添加空间索引
ALTER TABLE house ADD COLUMN location POINT NOT NULL SRID 4326;
CREATE SPATIAL INDEX idx_location ON house(location);
-- 查询5公里范围内的房源
SELECT id, title, ST_Distance_Sphere(location, POINT(114.123, 30.456)) as distance
FROM house
WHERE ST_Distance_Sphere(location, POINT(114.123, 30.456)) <= 5000
ORDER BY distance;
对应的Django ORM查询:
python复制from django.contrib.gis.db.models.functions import Distance
from django.contrib.gis.geos import Point
def nearby_houses(lng, lat, radius):
point = Point(lng, lat, srid=4326)
return House.objects.annotate(
distance=Distance('location', point)
).filter(distance__lte=radius).order_by('distance')
5. 毕业设计亮点打造建议
5.1 数据可视化分析
使用Pyecharts生成租房市场分析报表:
python复制from pyecharts.charts import Bar
from pyecharts import options as opts
def price_distribution_chart():
queryset = House.objects.values('district').annotate(
avg_price=Avg('price'),
count=Count('id')
).order_by('-avg_price')
bar = Bar()
bar.add_xaxis([x['district'] for x in queryset])
bar.add_yaxis("平均价格", [x['avg_price'] for x in queryset])
bar.add_yaxis("房源数量", [x['count'] for x in queryset])
bar.set_global_opts(
title_opts=opts.TitleOpts(title="各区域房源价格分布"),
toolbox_opts=opts.ToolboxOpts()
)
return bar.render_embed()
5.2 自动化测试方案
使用pytest编写接口测试:
python复制@pytest.mark.django_db
def test_house_search(client):
# 准备测试数据
House.objects.create(
title="测试房源",
address="武城市测试区",
area=80.00,
price=2000.00,
landlord_id=1
)
# 执行搜索
response = client.get('/api/houses/?max_price=2500')
# 验证结果
assert response.status_code == 200
assert len(response.json()) == 1
assert response.json()[0]['title'] == "测试房源"
6. 项目部署与调试技巧
6.1 生产环境配置要点
推荐使用Docker Compose部署:
yaml复制version: '3'
services:
db:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: rootpass
MYSQL_DATABASE: rental
MYSQL_USER: rental
MYSQL_PASSWORD: rentalpass
volumes:
- mysql_data:/var/lib/mysql
backend:
build: ./backend
command: python manage.py runserver 0.0.0.0:8000
volumes:
- ./backend:/code
ports:
- "8000:8000"
depends_on:
- db
frontend:
build: ./frontend
ports:
- "8080:8080"
volumes:
mysql_data:
6.2 常见调试问题解决
- 跨域问题:确保Django配置中包含:
python复制CORS_ALLOWED_ORIGINS = [
"http://localhost:8080",
"http://127.0.0.1:8080"
]
- 静态文件404:生产环境需要配置:
python复制STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')
STATIC_URL = '/static/'
- 时区问题:建议统一设置:
python复制TIME_ZONE = 'Asia/Shanghai'
USE_TZ = True
在开发这个系统的过程中,我发现最大的挑战不是技术实现,而是业务流程的准确建模。比如合同状态流转、押金退还规则等,都需要与实际的租房业务流程高度吻合。建议开发前先绘制完整的业务流程图,并与有租房经验的人确认细节,这能避免后期大量的逻辑修改。
