[特殊字符] 技术深度解析:基于Django+微信小程序+通义千问VL的房树人心理测试系统
📋 项目概述(源码已放在文章末尾)
这是一个完整的房树人(House-Tree-Person)心理测试AI分析系统,结合了Django后端、微信小程序前端和通义千问VL大模型。系统允许用户绘制或上传房树人图像,通过AI进行专业的心理分析,并生成详细的分析报告。技术栈涵盖:
-
后端:Django 4.2 + Django REST Framework
-
前端:微信小程序原生开发 + Canvas API
-
AI模型:通义千问VL大模型(图像理解能力)
-
数据库:SQLite3(可扩展至MySQL/PostgreSQL)
-
支付系统:完整微信支付集成
-

系统实现了用户绘制/上传房树人图像 → AI智能分析 → 生成专业心理报告的全流程。
🏗️ 技术架构设计
系统架构图
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ 微信小程序前端 │───▶│ Django后端API │───▶│ AI大模型服务 │
│ │ │ │ │ │
│ • Canvas绘画板 │ │ • RESTful API │ │ • 通义千问VL │
│ • 图片上传 │ │ • 流式响应 │ │ • 图像理解 │
│ • 支付集成 │ │ • 数据库操作 │ │ • 心理分析 │
│ • 广告组件 │ │ • 异步任务 │ │ │
└─────────────────┘ └─────────────────┘ └─────────────────┘
│
▼
┌─────────────────┐
│ 数据库 │
│ │
│ • 用户记录 │
│ • 分析结果 │
│ • 订单信息 │
└─────────────────┘
技术架构特点
-
前后端分离:微信小程序前端 + Django REST API后端
-
流式响应:改善AI分析长时等待体验
-
支付集成:完整微信支付系统对接
-
微服务化:AI服务独立,便于扩展和替换
💻 核心技术实现
1. Canvas绘画板技术实现
微信小程序Canvas绘图
// pages/draw/draw.js - 核心绘图逻辑
Page({
data: {
ctx: null,
canvas: null,
isDrawing: false,
lastX: 0,
lastY: 0,
lineWidth: 5,
currentColor: '#2c3e50'
},
// 初始化Canvas - 处理高清屏适配
initCanvas() {
const query = wx.createSelectorQuery()
query.select('#drawCanvas')
.fields({ node: true, size: true })
.exec((res) => {
const canvas = res[0].node
const ctx = canvas.getContext('2d')
// 设备像素比适配
const dpr = wx.getSystemInfoSync().pixelRatio
canvas.width = res[0].width * dpr
canvas.height = res[0].height * dpr
ctx.save()
ctx.scale(dpr, dpr)
// 设置画笔属性
ctx.lineCap = 'round'
ctx.lineJoin = 'round'
ctx.lineWidth = this.data.lineWidth
ctx.strokeStyle = this.data.currentColor
this.setData({ ctx, canvas })
})
},
// 触摸事件处理
touchStart(e) {
const { x, y } = e.touches[0]
this.setData({
isDrawing: true,
lastX: x,
lastY: y
})
},
touchMove(e) {
if (!this.data.isDrawing) return
const { x, y } = e.touches[0]
const { ctx, lastX, lastY } = this.data
// 贝塞尔曲线平滑绘制
ctx.beginPath()
ctx.moveTo(lastX, lastY)
ctx.lineTo(x, y)
ctx.stroke()
this.setData({
lastX: x,
lastY: y
})
}
})
图片上传和适配处理
// 图片上传和Canvas绘制适配
chooseImage() {
wx.chooseImage({
count: 1,
success: (res) => {
const tempFilePath = res.tempFilePaths[0]
const image = this.data.canvas.createImage()
image.src = tempFilePath
image.onload = () => {
const { ctx, canvas } = this.data
// 计算图片适配尺寸 - 保持宽高比
const imageRatio = image.width / image.height
const canvasRatio = canvas.width / canvas.height
let drawWidth, drawHeight, x, y
if (imageRatio > canvasRatio) {
// 图片更宽,以宽度为基准
drawWidth = canvas.width
drawHeight = canvas.width / imageRatio
x = 0
y = (canvas.height - drawHeight) / 2
} else {
// 图片更高,以高度为基准
drawHeight = canvas.height
drawWidth = canvas.height * imageRatio
x = (canvas.width - drawWidth) / 2
y = 0
}
// 清除画布并绘制图片
ctx.clearRect(0, 0, canvas.width, canvas.height)
ctx.drawImage(image, x, y, drawWidth, drawHeight)
}
}
})
}
2. Django后端AI分析系统
核心分析接口实现
# apps/users/views.py - AI分析核心逻辑
@csrf_exempt
@require_http_methods(["POST"])
def analyze(request):
try:
# 解析请求数据
data = json.loads(request.body)
image_data = data.get('image')
if not image_data:
return JsonResponse({'error': '未接收到图片数据'}, status=400)
# 初始化通义千问VL大模型
model = ChatOpenAI(
model="qwen3-vl-plus",
openai_api_key=settings.OPENAI_API_KEY,
temperature=0.0,
request_timeout=300,
max_retries=1,
max_tokens=8192,
base_url="https://dashscope.aliyuncs.com/compatible-mode/v1",
)
# 构建心理学分析Prompt
prompt = ChatPromptTemplate.from_messages([
("system", config.PROMPT_INSTRUCTIONS_HTML),
("user", [
{"type": "text", "text": "这是我画的,请帮我分析"},
{"type": "image_url", "image_url": {"url": f"{image_data}"}},
]),
])
chain = prompt | model
# 流式响应生成器 - 实时返回分析结果
def generate():
analysis_results = ''
for chunk in chain.stream({"image_data": image_data}):
analysis_results += chunk.content
yield json.dumps({
'type': 'text',
'content': chunk.content
}) + '\n'
# 保存分析记录到数据库
record = AnalysisRecord.objects.create(
image_data=image_data,
analysis_result=analysis_results,
request_time=datetime.now(),
process_duration=(datetime.now() - request_start_time).total_seconds(),
payment_status='unpaid'
)
yield json.dumps({
'type': 'objectID',
'content': f"{str(record.id)}"
}) + '\n'
# 返回流式HTTP响应
return StreamingHttpResponse(generate(), content_type='application/json')
except Exception as e:
logger.error(f"分析失败: {str(e)}")
return JsonResponse({'error': str(e)}, status=500)
数据库模型设计
# apps/users/models.py - 数据模型设计
class AnalysisRecord(models.Model):
"""房树人测试分析记录"""
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
image_data = models.TextField(verbose_name="图片数据")
analysis_result = models.TextField(verbose_name="分析结果")
request_time = models.DateTimeField(verbose_name="请求时间")
process_duration = models.FloatField(verbose_name="处理用时(秒)")
payment_status = models.CharField(
max_length=20,
default="unpaid",
verbose_name="支付状态",
choices=[("unpaid", "未支付"), ("paid", "已支付")]
)
created_at = models.DateTimeField(auto_now_add=True, verbose_name="创建时间")
class Meta:
verbose_name = "分析记录"
verbose_name_plural = "分析记录"
ordering = ['-created_at']
def __str__(self):
return f"分析记录 {self.id} - {self.payment_status}"
class HTPOrder(models.Model):
"""房树人测试订单"""
out_trade_no = models.CharField(max_length=100, unique=True, verbose_name="订单号")
status = models.CharField(
max_length=20,
default="unpaid",
verbose_name="订单状态",
choices=[("unpaid", "未支付"), ("paid", "已支付")]
)
timestamp = models.DateTimeField(auto_now_add=True, verbose_name="创建时间")
class Meta:
verbose_name = "订单"
verbose_name_plural = "订单"
ordering = ['-timestamp']
def __str__(self):
return f"订单 {self.out_trade_no} - {self.status}"
3. AI Prompt工程实现
心理学分析Prompt设计
# config.py - 专业心理学Prompt设计
PROMPT_INSTRUCTIONS_HTML = """# Role
心理测试分析师,分析用户绘制的房树人测试图,提供个性化解读和心理建议。
## Action
模型基于用户提供的房树人测试图,逐一分析房子、树和人物的细节、结构、比例、位置以及其他特征。通过这些元素的分析,评估用户的心理状态、性格特征、潜在情感需求,并给出针对性的心理暗示与建议。
## Skills
- 扎实的心理学理论基础,尤其是在投射测试和心理评估方面
- 优秀的观察力和敏锐的心理分析能力,能够解读绘画中的微妙心理信号
- 精确的语言表达与总结能力,能够将复杂的心理信息转化为通俗易懂的分析结果
- 熟练掌握房树人测试的框架和解读方法
- 能够灵活应对不同绘画风格,适应性地调整分析角度
## Format
- 输出结果使用HTML排版,确保内容结构清晰,易于用户阅读。
- 每个分析部分(如房子、树、人物等)需分别作为一个独立的`div`区块,包含标题和具体分析内容。
- 每个分析内容分为小节,涵盖具体的心理解读,并在适当位置加入心理暗示和总结建议。
- 分析内容应简洁明了,避免复杂的心理学术语,确保用户易于理解。
- 每段文字都必须使用标签包裹,以便于前端解析。
## Constraints
- 每个分析部分需包含详细的心理解读,并根据绘画的细节、比例、结构等给出具体的建议。
- 保证分析结果层次分明,每个部分都应清晰标明标题和分析内容。
- 内容应具有较高的专业性,但避免过于学术化,语言要易于理解。
- HTML排版结构需语义化,确保便于网页呈现和用户浏览。
"""
4. 支付系统技术实现
微信小程序支付集成
// pages/report/report.js - 支付功能实现
getPayOrderId() {
const that = this
const secretKey = 'ylA82pMGHHkUYXw0Mgb5xasXQoScPX8n'
const resultId = this.data.resultId
var params = {
pid: '20230210011731',
cid: '10450',
type: 'wxpay',
out_trade_no: resultId,
notify_url: app.globalData.host + '/htp/api/payment_notification_by_no',
name: '房树人心理测试',
money: that.data.price,
clientip: '192.168.1.100',
device: 'pc',
param: resultId,
sign_type: 'MD5',
};
// 生成MD5签名
const sign = generateSign(params, secretKey);
params.sign = sign;
// 调用支付接口
wx.request({
url: 'https://zpayz.cn/mapi.php',
method: 'POST',
data: params,
header: {
'content-type': 'application/x-www-form-urlencoded'
},
success(res) {
if(res.data && res.data.code === 1) {
// 显示支付二维码
that.setData({
qrCodeImage: res.data.img
});
// 轮询查询支付状态
const intervalId = setInterval(() => {
wx.request({
url: app.globalData.host + '/htp/api/check_payment_status_by_no',
method: 'GET',
data: { out_trade_no: resultId },
success(response) {
if (response.data.payment_status === 'paid') {
clearInterval(intervalId);
that.setData({ loading: true });
that.analyzeDrawing(); // 支付成功后调用分析
}
}
});
}, 2000);
}
}
});
}
Django支付回调处理
# apps/users/views.py - 支付回调接口
@require_http_methods(["GET"])
def payment_notification_by_no(request):
try:
# 获取所有请求参数
params = request.GET.dict()
print("接收到的支付通知参数:", params)
# 从参数中获取param值
param = params.get('param')
# 检查交易状态
trade_status = params.get('trade_status')
if trade_status == 'TRADE_SUCCESS':
# 创建或更新订单记录
order, created = HTPOrder.objects.get_or_create(
out_trade_no=param,
defaults={'status': 'paid'}
)
if not created:
order.status = 'paid'
order.save()
print(f"订单记录 {param} 添加/更新成功")
# 返回成功响应
return HttpResponse('success')
except Exception as e:
return JsonResponse({'error': str(e)}, status=500)
5. 流式响应处理技术
前端流式响应解析
// 流式响应处理 - 实时显示AI分析结果
analyzeDrawing() {
const startTime = Date.now()
const that = this
wx.request({
url: app.globalData.host + '/htp/api/analyze',
method: 'POST',
data: { image: this.data.drawingImage },
timeout: 180000,
responseType: 'text',
success(res) {
const lines = res.data.split('\n')
let content = ''
for (const line of lines) {
if (!line.trim()) continue
try {
const data = JSON.parse(line)
if (data.type === 'text') {
// 处理HTML内容
let processedContent = data.content
.replaceAll('```', '')
.replaceAll('html', '')
.replaceAll('<h4>', '<h4 style="border-left: 4px solid #4a90e2;padding-left: 15px;color:#4a90e2;margin: 20px 0;">')
content += processedContent
}
} catch (e) {
console.error('解析错误:', e)
}
}
that.setData({
loading: false,
analysisContent: content,
analysisTime: ((Date.now() - startTime) / 1000).toFixed(2)
})
}
})
}
🔧 部署与配置
1. 环境配置
# 安装Python依赖
pip install -r requirements.txt
# 数据库迁移
python manage.py migrate
2. Django配置
# settings.py - 关键配置
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'rest_framework',
'django_celery_results',
'apps.users'
]
# Celery配置
CELERY_BROKER_URL = 'redis://localhost:6379/0'
CELERY_RESULT_BACKEND = 'redis://localhost:6379/0'
CELERY_ACCEPT_CONTENT = ['json']
CELERY_TASK_SERIALIZER = 'json'
CELERY_RESULT_SERIALIZER = 'json'
CELERY_TIMEZONE = 'Asia/Shanghai'
3. 启动服务
# 启动Django服务
python manage.py runserver 0.0.0.0:8000
📈 项目总结
技术亮点
-
全栈开发:完整的Django后端 + 微信小程序前端
-
AI集成:通义千问VL大模型的深度集成
-
流式响应:改善用户体验的实时反馈机制
-
支付系统:完整微信支付集成
-
跨平台:微信小程序的多设备兼容性
学习价值
通过这个项目,开发者可以学习到:
-
Django REST Framework的API设计
-
微信小程序Canvas绘图技术
-
AI大模型的集成与应用
-
流式响应的实现原理
-
支付系统对接技术
-
生产环境的部署和优化
应用场景
-
心理教育:学校心理辅导工具
-
自我认知:个人心理状态评估
-
心理咨询:专业咨询师的辅助工具
-
社交娱乐:朋友间的心理测试游戏
📦 获取源码
完整的项目源码已经整理好,包含:
-
完整的Django后端代码
-
微信小程序前端代码
-
数据库迁移文件
-
部署配置脚本
-
详细的开发文档
-
支付系统对接代码
关注公众号【AI创业指南】,回复【房树人源码】即可获取完整项目源码。

💬 技术交流
如果在部署或使用过程中遇到任何技术问题,欢迎通过以下方式交流:
-
在公众号留言技术问题
希望这个项目能为你提供有价值的技术参考,也欢迎提出技术改进建议和功能需求。
立即获取源码,开始你的全栈AI项目开发之旅!
更多推荐



所有评论(0)