VX提交表格,DJango后台返显时,部门、聘任关系两个字段没有显示相应内容---几种解决方案如下
1、问题
部门、聘任关系没有显示相应内容
2.解决方案一:
现象
单元格能渲染出来,但是 depart、relation 看不到内容;其他字段(username、IDnumber)正常显示。
<view class="td dpt">{{item.depart.id}}-{{item.depart.name}}</view>
<view class="td rel">{{item.relation.id}}-{{item.relation.name}}</view>
大概率两种情况:
- 后端返回
depart / relation为null(数据库该字段允许为空,记录没绑定部门/关系),小程序渲染null‑undefined,看起来空白。 - DRF序列化器没有把depart、relation嵌套对象输出,接口返回的list里面
item.depart不是对象,而是单纯数字id,前端直接取.id/.name→ 拿不到,显示空白。
第一步:看小程序Network,查看接口返回json
找到你的 /online_collection/preregistration/ 返回数据,看一条记录:
✅正常应该:
"depart":{"id":2,"name":"技术部"},
"relation":{"id":1,"name":"正式员工"}
❌异常1(最常见):
"depart":2,
"relation":1
只返回id数字,不是对象,前端写
item.depart.name等价于2.name→ undefined,单元格空白。
❌异常2:
"depart":null,
"relation":null
数据库这条记录外键为空。
修复后端序列化器(核心,如果只返回id数字)
你的 PreregSerializer,外键默认只会输出id,需要改成嵌套输出对象。
# 先写子序列化器
class DepartSerializer(serializers.ModelSerializer):
class Meta:
model = Depart
fields = ['id','name']
class RelationSerializer(serializers.ModelSerializer):
class Meta:
model = Relation
fields = ['id','name']
class PreregSerializer(serializers.ModelSerializer):
# 嵌套输出完整对象
depart = DepartSerializer(read_only=True)
relation = RelationSerializer(read_only=True)
created_at = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S", read_only=True)
class Meta:
model = Preregistration
fields = "__all__"
保存,重启django服务,刷新小程序,再看接口返回,depart、relation变成对象格式。
⚠️如果你是做PATCH修改接口,写操作不要用嵌套序列化;read_only=True只用于读取列表,不影响提交保存。
前端兼容兜底(防止为null时报错空白)
wxml增加判断,如果对象为空,显示-,避免渲染异常:
<view class="td dpt">
{{item.depart?(item.depart.id+'-'+item.depart.name):'-'}}
</view>
<view class="td rel">
{{item.relation?(item.relation.id+'-'+item.relation.name):'-'}}
</view>
额外:你当前wxml还有一个严重错误
你又写回了:
<view scroll-x scroll-y class="table-wrap" >
又使用了scroll‑view组件(这里你把标签写错了,不是<scroll-view>,写成<view>加了scroll‑x属性!普通view不识别scroll‑x、scroll‑y!!)
❗普通
<view>写scroll-x scroll-y属性完全无效!!
- 如果要使用组件:标签必须是
<scroll-view scroll-x scroll-y> - 如果使用css overflow:标签是普通
<view>,删掉全部scroll‑x scroll‑y属性。
修正你的wxml标签(CSS overflow方案)
<!--表格容器 普通view,删除scroll‑x scroll‑y属性!!-->
<view class="table-wrap">
<!--内表格容器-->
<view class="table-inner">
<!--表头-->
<view class="table-header">
<view class="td number">序号</view>
<view class="td operate">编辑操作</view>
<view class="td time">登记时间</view>
<view class="td name ">用户姓名</view>
<view class="td IDcard">身份证号</view>
<view class="td tel ">手机号</view>
<view class="td email">电子邮箱</view>
<view class="td dpt">隶属部门</view>
<view class="td rel">聘用关系类型</view>
</view>
<!--表格行-->
<view wx:for="{{list}}" wx:key="id" wx:for-index="idx" class="table-row">
<view class="td number">{{idx+1}}</view>
<view class="td operate">
<text bind:tap="bindMod_row" data-index="{{idx}}">修改</text>
<text bind:tap="bindDel_row" data-index="{{idx}}">删除</text>
</view>
<view class="td time">{{item.created_at}}</view>
<view class="td name">{{item.username}}</view>
<view class="td IDcard">{{item.IDnumber}}</view>
<view class="td tel">{{item.phone}}</view>
<view class="td email">{{item.email}}</view>
<view class="td dpt">
{{item.depart?(item.depart.id+'-'+item.depart.name):'-'}}
</view>
<view class="td rel">
{{item.relation?(item.relation.id+'-'+item.relation.name):'-'}}
</view>
</view>
</view>
</view>
排查顺序总结
- 看Network接口响应,确认depart、relation是对象还是单纯数字id;
- 如果只是id,后端序列化器增加嵌套子序列化器;
- 前端加上三元表达式兜底null;
- 标签注意:普通view不能写scroll‑x / scroll‑y,这是scroll‑view组件专属属性。
补充:如果你不想嵌套序列化,前端也可以只拿到id,本地做映射,但是后端嵌套输出是最标准做法。
3.方案2、3
方案:后端只返回 depart、relation 的ID,前端做本地映射
后端序列化器保持原样,不写嵌套Serializer,接口返回:
"depart": 2,
"relation": 1
前端预先存好部门字典、聘用关系字典,根据id翻译成name。
1.小程序js页面data中定义字典
Page({
data:{
list:[], // 预约列表
// 部门字典 key为id,value为name
departMap:{
1:"行政部",
2:"技术部",
3:"财务部"
},
//聘用关系字典
relationMap:{
1:"正式员工",
2:"劳务派遣",
3:"外包"
}
},
// 获取列表接口
getDataList(){
wx.request({
url:"你的列表接口地址",
success:(res)=>{
if(res.data.code===200){
this.setData({
list:res.data.result
})
}
}
})
}
})
2.WXML 使用字典映射
<view class="td dpt">
{{item.depart}}‑{{departMap[item.depart] || '-'}}
</view>
<view class="td rel">
{{item.relation}}‑{{relationMap[item.relation] || '-'}}
</view>
departMap[item.depart]:拿id去字典找对应名称|| '-':id不存在/为空的时候显示横杠,不显示undefined
⚠️缺点(重点)
- 后端新增部门/关系,前端js字典必须手动同步修改,两边维护,容易不同步;
- 如果后端数据库数据很多,字典写死在前端不灵活;
✅更好改良:单独拿字典接口(推荐)
后端写两个简单接口,返回全部部门列表、全部聘用关系列表,小程序启动时请求一次,生成映射表,不用硬编码写死。
js示例
Page({
data:{
list:[],
departMap:{},
relationMap:{}
},
// 生成字典映射
buildMap(arr,keyName,valName){
let map = {}
arr.forEach(item=>{
map[item[keyName]] = item[valName]
})
return map
},
async initDict(){
// 请求部门接口
const resDept = await this.requestApi("/online_collection/depart_list/")
// 请求关系接口
const resRel = await this.requestApi("/online_collection/relation_list/")
this.setData({
departMap:this.buildMap(resDept.data.result,"id","name"),
relationMap:this.buildMap(resRel.data.result,"id","name")
})
},
onLoad(){
this.initDict() //页面加载先加载字典
this.getDataList() //再加载表格数据
}
})
两种方案对比
| 方案 | 优点 | 缺点 |
|---|---|---|
| 后端嵌套序列化 | 前端不用管映射,数据完全由后端维护 | 序列化代码多;PATCH更新接口要注意read_only=True,不能传入写 |
| 前端硬编码字典 | 不用改后端序列化器 | 前后端要同步维护字典,容易不一致 |
| 前端请求字典接口 | 字典由后端维护,前端自动生成映射 | 多2次http请求 |
你的场景,如果部门、聘用关系几乎不会改动,直接硬编码字典最简单。
如果后台可以新增修改部门,建议做单独字典接口。
额外小坑
数据库外键字段允许为空时,item.depart有可能是null,wxml渲染 null‑-,不影响显示。
如果你需要,我可以给你写后端depart_list、relation_list极简view和urls。
浙公网安备 33010602011771号