〔十四〕员工信息模型:60个字段的设计思路与验证器

发布时间:2026/7/15 6:28:46
〔十四〕员工信息模型:60个字段的设计思路与验证器 阅读提示感谢你阅读本章。本文所有代码和注释均来自真实项目为了能让更多认真学习的读者持续获得优质内容本文将在7天后转为“粉丝可见”。如果你觉得本文有价值欢迎收藏并关注我本系列博客将继续保持同样详细的注释风格。感谢理解与支持一、业务场景在第5-13章我们完成了组织机构模块部门、用户资料、权限。现在需要管理企业全体员工的档案信息包括基础信息员工编码、姓名、身份证、头像个人基本信息性别、民族、出生日期、婚姻状况、联系电话等教育背景毕业院校、专业、学历工作信息参工时间、职位、工种、员工状态等组织与政治信息入党时间、政治面貌、岗位层级资质信息资格级别、资格名称特殊标记违法犯罪记录、特殊人员、退役军人、军人家属—— 跨模块联动的关键开关审计与软删除字段这些字段总数超过60个并且有大量 Choice 枚举民族、政治面貌、学历、员工状态等。模型设计要兼顾录入效率Admin 字段分组、数据质量验证器、查询性能冗余显示字段、索引。与组织机构模块的区别组织机构模型Department、UserProfile字段较少且UserProfile仅针对系统管理者。员工模型是全量人事档案字段多、枚举细、验证规则复杂是企业管理的核心数据源。二、模型字段分类总览下面按业务逻辑将60字段分为8大类方便理解。分类字段列表说明基础信息employee_number,full_name,id_number,avatar唯一编码、姓名、身份证、头像个人基本信息gender,gender_display,nation,nation_display,birth_date,native_place,marital_status,marital_status_display,phone,permanent_address含冗余显示字段教育背景graduation_school,first_major,graduation_date,first_education,first_education_display第一学历、毕业信息工作信息join_work_date,position,job_type,actual_unit,employee_status,employee_status_display,employee_group,employee_subgroup含员工状态细粒度组织与政治信息join_organization_date,political_status,political_status_display,position_level,position_level_display,personal_identity,personal_identity_display政治面貌、岗位层级、个人身份资质信息qualification_level,qualification_level_display,qualification_name,qualification_name_display职称/资格特殊标记has_criminal_record,is_special_personnel,is_veteran,is_military_family跨模块联动开关审计软删除created_at,updated_at,created_by,updated_by,is_deleted,deleted_at,deleted_by,delete_reason与第6章相同复用设计三、特殊标记字段跨模块联动的数据开关核心亮点这四个布尔字段不是简单的“是/否”记录而是整个系统的行为开关。它们控制着其他业务模块的数据显示、录入权限和业务规则。字段业务含义在后续模块中的用途has_criminal_record有无违法犯罪记录违法违纪管理只有标记为“有”的员工才能在案件模块中被关联。在案件记录的“关联员工”下拉框中自动过滤掉has_criminal_recordFalse的员工从源头防止错误关联。is_special_personnel是否特殊人员如重点稳控对象安保防恐排查在重点部位、工单任务中系统自动高亮标记特殊人员提醒保卫人员重点监控。is_veteran是否退役军人先进个人申报在评优评先时系统可自动统计退役军人占比工单任务可优先分配给退役军人党员等。is_military_family是否军人家属节假日慰问系统可筛选出军人家属生成慰问名单帮扶救助优先考虑军属家庭。设计理念数据源头控制一次标记多处联动。例如当一名员工在员工信息表中勾选has_criminal_record True后在违法违纪模块的“关联员工”下拉框中该员工会自动出现而其他员工不出现。选择该员工后系统自动从员工表读取姓名、部门、身份证等信息填充到案件的快照字段中避免重复录入。在案件统计报表中该员工会被计入违法犯罪人员统计。代码示例第7章已实现此处仅展示调用方式# illegalcase/admin.py 中的 formfield_for_foreignkeydefformfield_for_foreignkey(self,db_field,request,**kwargs):ifdb_field.nameemployee:# 只显示 has_criminal_recordTrue 的员工qsEmployeeBasicInfo.objects.filter(has_criminal_recordTrue,department_id__inviewable_dept_ids,is_deletedFalse)# ... 其他配置如果没有这些特殊标记字段违法违纪模块就无法自动筛选符合条件的人员需要人工去核对既低效又容易出错。这就是为什么员工基础信息是后续所有业务模块的“数据基石”——没有准确的员工标记后续的案件管理、安保排查、工单流转等都无从谈起。四、冗余显示字段的设计性能优化亮点在员工模型中很多字段是 ChoiceField如性别、民族、员工状态。数据库存储的是代码如 ‘在册在岗’但在 Admin 列表页我们希望直接显示中文而不是每次都调用 get_xxx_display()会产生额外查询。解决方案增加冗余字段xxx_display在 save() 中自动从 Choice 代码填充显示值。查询时直接读取该字段无需调用方法。# models.py简化示例gendermodels.CharField(max_length10,choicesGENDER_CHOICES,nullTrue,blankTrue)gender_displaymodels.CharField(max_length10,blankTrue,nullTrue,help_text自动从性别字段填充)在 save() 中调用 _fill_display_fields() 方法见第七节。五、字段验证器模型层统一验证验证器写在字段的 validators 参数中确保无论通过 Admin、导入、API 保存数据都会执行验证。5.1 手机号验证器 validate_phonedefvalidate_phone(value):ifvalue:# 支持手机号含86、座机区号-号码、纯数字7-8位patternr^(\?86)?1[3-9]\d{9}$|^0\d{2,3}-?\d{7,8}$|^\d{7,8}$ifnotre.match(pattern,value.replace( ,)):raiseValidationError(请输入有效的联系电话格式手机号或座机)5.2 身份证基本格式验证 validate_id_numberdefvalidate_id_number(value):ifnotvalue:return# 15位或18位最后一位可为Xifnotre.match(r^(\d{15}|\d{17}[\dXx])$,value):raiseValidationError(身份证号码格式不正确15位或18位)注意内部项目无法接入公安接口只做基本格式校验。5.3 头像大小验证 validate_image_sizedefvalidate_image_size(value):limit2*1024*1024# 2MBifvalueandvalue.sizelimit:raiseValidationError(图片大小不能超过2MB)5.4 头像上传路径 employee_avatar_pathdefemployee_avatar_path(instance,filename):# 防止路径遍历攻击替换 / 和 \safe_numberstr(instance.employee_number).replace(/,_).replace(\\,_)extfilename.split(.)[-1]if.infilenameelsejpgreturnfemployee_avatars/{safe_number}.{ext}六、Choice 枚举定义部分模型中定义了十几个 Choice 元组例如POLITICAL_CHOICES[(中共党员,中共党员),(预备中共党员,预备中共党员),(共青团员,共青团员),(群众,群众),(民主党派,民主党派),# ...]STATUS_CHOICES[(在册在岗,在册在岗),(在册不在岗,在册不在岗),(在册不在岗-其他,在册不在岗-其他),(退休,退休),(调出,调出),# ...]这些枚举贴近国企真实业务体现了数据的精细度。七、save() 方法重写defsave(self,*args,**kwargs):# 1. 自动填充冗余显示字段self._fill_display_fields()# 2. 同步部门快照如果有关联部门ifself.department:self.department_nameself.department.nameelse:self.department_namesuper().save(*args,**kwargs)_fill_display_fields() 内部使用 get_xxx_display() 方法填充显示字段仅当为空时填充避免覆盖用户手动修改。八、软删除与审计字段复用第6章员工模型直接继承了与 Department 相同的软删除和审计字段设计包括· is_deleted, deleted_at, deleted_by, delete_reason· created_at, updated_at, created_by, updated_by具体原理见第6章本章不再重复。九、元数据与索引classMeta:verbose_name员工基础信息verbose_name_plural员工基础信息ordering[employee_number]indexes[models.Index(fields[department,is_deleted]),models.Index(fields[is_archived,is_deleted]),]为常用联合查询字段添加索引提升列表页性能。十、注意事项踩坑经验序号注意事项踩坑总结1冗余显示字段只填充一次_fill_display_fields 中判断 if not self.gender_display 再赋值避免每次保存都覆盖用户可能手动修正的值2头像路径安全使用 replace 过滤路径分隔符防止恶意上传 …/…/config.py 导致文件覆盖3身份证验证不严格内部系统够用若需更强校验可接入第三方 API4员工状态枚举值很长如“在册不在岗-其他长期休假人员(六个月以上)”在 Admin 下拉框中会折行不影响功能5nullTrue 与 blankTrue大多数业务字段允许空blankTrue因为历史数据可能不完整6与组织机构模块的区分UserProfile 是系统使用者管理员EmployeeBasicInfo 是全体员工。两者通过 employee_id 或 employee_number 可关联但非强制7特殊标记字段的初始值默认均为 False需要由保卫干事根据实际情况勾选。一旦标记后续模块立即生效十一、小结本章完成了员工信息模型的全解析· 60 字段按业务分类· 四个特殊标记字段的跨模块联动价值重点· 冗余显示字段的性能优化· 三大字段验证器手机号、身份证、头像· Choice 枚举的组织· save() 重写自动填充· 复用第6章的软删除/审计至此员工信息的数据结构已就绪并且明确了它在整个系统中的“数据基石”地位。 下一章我们将进入 员工数据导入包括模板生成、三步验证、逐行事务处理以及“导出→修改→导入”的完美闭环。互动问题你的业务系统中有哪些类似的“标记字段”用来控制其他模块的行为欢迎评论区分享你的设计思路。