VX提交表格,DJango后台返显时,部门、聘任关系两个字段没有显示相应内容---几种解决方案如下

1、问题

序号 编辑操作 登记时间 用户姓名 身份证号 手机号 隶属部门 聘用关系类型




{{idx+1}}

修改
删除

{{item.created_at}}
{{item.username}}
{{item.IDnumber}}
{{item.phone}}

{{item.depart.id}}-{{item.depart.name}}
{{item.relation.id}}-{{item.relation.name}}



部门、聘任关系没有显示相应内容
2.解决方案一:

现象

单元格能渲染出来,但是 departrelation 看不到内容;其他字段(username、IDnumber)正常显示。

<view class="td dpt">{{item.depart.id}}-{{item.depart.name}}</view>
<view class="td rel">{{item.relation.id}}-{{item.relation.name}}</view>

大概率两种情况:

  1. 后端返回 depart / relationnull(数据库该字段允许为空,记录没绑定部门/关系),小程序渲染 null‑undefined,看起来空白。
  2. 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>

排查顺序总结

  1. 看Network接口响应,确认depart、relation是对象还是单纯数字id;
  2. 如果只是id,后端序列化器增加嵌套子序列化器;
  3. 前端加上三元表达式兜底null;
  4. 标签注意:普通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

⚠️缺点(重点)

  1. 后端新增部门/关系,前端js字典必须手动同步修改,两边维护,容易不同步;
  2. 如果后端数据库数据很多,字典写死在前端不灵活;

✅更好改良:单独拿字典接口(推荐)

后端写两个简单接口,返回全部部门列表、全部聘用关系列表,小程序启动时请求一次,生成映射表,不用硬编码写死。

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。

posted @ 2026-08-16 11:45  ham0921  阅读(2)  评论(0)    收藏  举报