飞书配置表数据同步到数据库中

这是我的从飞书取数据的代码

python 复制代码
def get_employee_from_feishu():
    staff_setting  = settings.FEISHU_SETTING["sales_order"]["employee"]
    app_token = staff_setting ["app_token"]
    table_id = staff_setting ["table_id"]

    page_token = None
    hasMore = True
    employees = {}

    while hasMore:
        staff_data = bitable_service.fetch(app_token, table_id, page_token=page_token)
        # 格式参考warehouse.json
        hasMore = staff_data["data"]["has_more"]
        rows = staff_data["data"]["items"]

        for row in rows:
            fields = row["fields"]
            if "姓名" in fields:
                employee = {
                    "employee_id": fields.get("工号"),
                    "name": fields.get("姓名"),
                    "position": fields.get("人员.职务"),
                    "department": fields.get("部门名"),
                }
                employees[employee["name"]] = employee

        if not hasMore:
            break
        page_token = staff_data["data"].get("page_token")

    return employees

这是我的数据库模型

python 复制代码
from django.db import models


class EmployeeModel(models.Model):
    employee_id = models.CharField(max_length=100, unique=True, null=True, blank=True, verbose_name="工号")
    name = models.CharField(max_length=64, null=True, blank=True, verbose_name="姓名")
    position = models.CharField(max_length=100, null=True, blank=True, verbose_name="人员.职务")
    department = models.CharField(max_length=100, null=True, blank=True, verbose_name="部门名")

    class Meta:
        db_table = "xss_employee"
        verbose_name = "员工信息"
        verbose_name_plural = "员工信息"

    def __str__(self):
        return self.name

这是我将飞书数据进入数据库的代码

python 复制代码
from core.models import EmployeeModel
from eccang.services.base_data_fetch_service import (
    get_product_category_from_feishu,
    get_warehouse_from_feishu,
    get_employee_from_feishu,
    get_country_from_feishu,
    get_monthly_target_from_feishu,
    get_position_target_from_feishu,
)



def sync_employee_to_db():
    data_dict = get_employee_from_feishu()
    for data in data_dict.values():
        if not data["employee_id"]:
            continue  # 跳过无工号数据

        EmployeeModel.objects.update_or_create(
            employee_id=data["employee_id"],
            defaults={
                "name": data["name"],
                "position": data["position"],
                "department": data["department"],
            }
        )

✅不错的地方

复制代码
使用分页抓取飞书数据,防止数据量大时漏数据。

使用 update_or_create,避免重复插入。

过滤掉没有 employee_id 的记录,防止插入空主键。

🔍建议优化点

  1. 字段容错性检查
    在访问字段时使用了 fields.get(),但在 position、department、employee_id 字段不是所有记录都存在时,可能得到 None。可以在构建 employee 字典时加默认值,避免报错或数据不一致:
python 复制代码
employee = {
    "employee_id": fields.get("工号", "").strip(),
    "name": fields.get("姓名", "").strip(),
    "position": fields.get("人员.职务", "").strip(),
    "department": fields.get("部门名", "").strip(),
}

注意 .strip() 可避免导入数据库中的空格异常。

  1. 避免空姓名造成 key 重复覆盖
    使用了 employees[employee["name"]] = employee,这会以"姓名"作为 key,而如果出现多个同名员工,可能被覆盖,造成数据丢失。

建议改为用 employee_id 做 key,更稳妥:

python 复制代码
employees[employee["employee_id"]] = employee
  1. 字段命名检查

    使用的是字段名如 "人员.职务",这是合法的,但建议在飞书中避免这种带点的字段名,因为它可能与 Python 字段语义混淆,或者将来你要做统一映射时会麻烦。

  2. 同步逻辑建议加日志(可选)

    可以加一点日志输出,方便调试或上线监控:

python 复制代码
import logging
logger = logging.getLogger(__name__)

def sync_employee_to_db():
    data_dict = get_employee_from_feishu()
    created, updated, skipped = 0, 0, 0

    for data in data_dict.values():
        if not data["employee_id"]:
            skipped += 1
            continue

        obj, is_created = EmployeeModel.objects.update_or_create(
            employee_id=data["employee_id"],
            defaults={
                "name": data["name"],
                "position": data["position"],
                "department": data["department"],
            }
        )
        if is_created:
            created += 1
        else:
            updated += 1

    logger.info(f"员工同步完成:新增 {created} 条,更新 {updated} 条,跳过 {skipped} 条")

✅ 总结

飞书分页抓取

空值处理

⚠️ 建议加默认值 .get(..., "").strip()

主键唯一性

⚠️ 建议用 employee_id 做 key

数据同步方式

✅ update_or_create 正确

日志与监控

⚠️ 建议加简单日志

字段命名规范性

⚠️ "人员.职务" 命名不够语义清晰,建议优化

下面是这段同步员工数据代码的详细结构分析,包括每一部分的职责、依赖关系、潜在问题和优化建议。

一、函数入口:sync_employee_to_db()

python 复制代码
def sync_employee_to_db():

作用:

主函数,负责执行"从飞书多维表格获取员工数据 → 写入本地数据库"的全过程。

二、从飞书获取数据

python 复制代码
data_dict = get_employee_from_feishu()

对应的函数:

python 复制代码
def get_employee_from_feishu():
    staff_setting  = settings.FEISHU_SETTING["sales_order"]["employee"]
    app_token = staff_setting ["app_token"]
    table_id = staff_setting ["table_id"]

    page_token = None
    hasMore = True
    employees = {}

    while hasMore:
        staff_data = bitable_service.fetch(app_token, table_id, page_token=page_token)
        hasMore = staff_data["data"]["has_more"]
        rows = staff_data["data"]["items"]

        for row in rows:
            fields = row["fields"]
            if "姓名" in fields:
                employee = {
                    "employee_id": fields.get("工号"),
                    "name": fields.get("姓名"),
                    "position": fields.get("人员.职务"),
                    "department": fields.get("部门名"),
                }
                employees[employee["name"]] = employee

        if not hasMore:
            break
        page_token = staff_data["data"].get("page_token")

    return employees

作用:

调用 bitable_service.fetch() 与飞书 API 通信;

按页遍历所有员工数据;

将每条员工记录解析为字典格式;

最后以 "姓名" 为 key 构造一个员工字典并返回。

依赖项:

bitable_service.fetch():对飞书多维表格的 API 封装;

settings.FEISHU_SETTING:飞书的 App Token 和表格 ID 来自配置文件;

字段名称如 "工号", "姓名", "人员.职务" 是 Feishu 表格中的字段。

潜在问题:

employees[employee["name"]] = employee:若员工同名会被覆盖;

若某行 fields 缺少必要字段,可能插入 None;

没有 .strip() 清洗字符串,可能出现数据不一致(如 "张三 " vs "张三");

若飞书接口失败,未处理异常(建议加 try-except);

三、同步到数据库

python 复制代码
for data in data_dict.values():
    if not data["employee_id"]:
        continue  # 跳过无工号数据

    EmployeeModel.objects.update_or_create(
        employee_id=data["employee_id"],
        defaults={
            "name": data["name"],
            "position": data["position"],
            "department": data["department"],
        }
    )

作用:

遍历每条员工数据;

以 "employee_id" 作为唯一键更新或插入 EmployeeModel;

若数据库中已存在对应 employee_id,则更新其他字段;

若不存在,则创建新记录。

优点:

update_or_create 可以自动处理"增"和"改",逻辑清晰;

使用 "employee_id" 作为唯一键,符合业务设计;

建议优化:

增加日志记录,比如:新增了多少条、更新了多少条;

对于姓名为空或异常的数据可以加校验;

加异常处理,防止单条数据出错影响整个同步流程。

四、模型结构分析:EmployeeModel

python 复制代码
class EmployeeModel(models.Model):
    employee_id = models.CharField(max_length=100, unique=True, null=True, blank=True, verbose_name="工号")
    name = models.CharField(max_length=64, null=True, blank=True, verbose_name="姓名")
    position = models.CharField(max_length=100, null=True, blank=True, verbose_name="人员.职务")
    department = models.CharField(max_length=100, null=True, blank=True, verbose_name="部门名")

    class Meta:
        db_table = "xss_employee"
        verbose_name = "员工信息"
        verbose_name_plural = "员工信息"

    def __str__(self):
        return self.name

字段解释:

字段名 类型 含义

employee_id CharField 员工工号,设为唯一键

name CharField 员工姓名

position CharField 职位/职务

department CharField 部门名称

建议:

如果业务上"工号"不可能为空,可以设置 null=False, blank=False;

添加 created_at、updated_at 字段,用于数据变更追踪;

可对 name 加索引提升查询效率(如果经常用 name 查询)。

五、完整建议汇总

数据来源字段容错 .get("字段", "").strip(),避免出现空值和空格

唯一键选择 不建议用 name 做 dict key,推荐用 employee_id

字段覆盖 如果同名员工存在,当前写法会覆盖后者数据,应避免

接口容错 加 try-except 捕获 Feishu API 错误

数据变更记录 加入 日志记录(如新增几条,更新几条)

模型增强 建议增加时间戳字段(created_at, updated_at)

配置来源 建议统一放到 settings,例如字段映射配置等,便于维护

相关推荐
web1309332039811 分钟前
Mysql的安装配置教程(非常详细)从零基础入门到精通,看完这一篇就够了
数据库·mysql
三天不学习12 分钟前
浅析AI大模型为何需要向量数据库?【入门基础】
数据库·人工智能·欧氏距离·向量数据库·余弦相似度
MonkeyKing_sunyuhua14 分钟前
将数据库结构化数据整合到RAG问答中的方式
数据库
喝醉酒的小白16 分钟前
MySQL内存使用率高问题排查与解决方案:
数据库
鹅鹅鹅呢16 分钟前
mysql 登录报错:ERROR 1045(28000):Access denied for user ‘root‘@‘localhost‘ (using password Yes)
android·数据库·mysql
摘星编程18 分钟前
Redis+Caffeine构建高性能二级缓存
数据库·redis·缓存
在人间负债^20 分钟前
假装自己是个小白 ---- 重新认识MySQL
android·数据库·mysql
檀越剑指大厂20 分钟前
【PostgreSQL系列】PostgreSQL性能优化
数据库·postgresql·性能优化
Leo.yuan26 分钟前
3D 数据可视化系统是什么?具体应用在哪方面?
大数据·数据库·3d·信息可视化·数据分析
元亓亓亓36 分钟前
MySQL--day1--数据库概述
数据库·mysql