如何编写内层函数解决字段名不同的Django遍历代码重复问题
解决方案
你可以通过传入姓名提取规则的方式消除重复,有以下几种常用实现方式:
方式1:把姓名提取逻辑作为函数参数传入
把公共逻辑封装为独立函数,遍历不同QuerySet时,传入对应获取姓名的lambda表达式即可:
# 先封装公共逻辑 def process_personnel(queryset, get_name): for item in queryset: name = get_name(item) # 其余完全一致的逻辑直接写在这里 ... # 调用时分别传入不同的姓名获取规则 managers = Manager.objects.all() process_personnel(managers, lambda m: f"{m.name.first_name} {m.name.last_name}") team_members = TeamMember.objects.all() process_personnel(team_members, lambda t: f"{t.member.first_name} {t.member.last_name}")
这种方式对原有代码侵入最小,不需要修改模型层代码,适合临时消除重复的场景。
方式2:给两个模型添加统一的姓名属性
如果后续还有多处需要统一获取姓名的逻辑,可以直接在Django模型层加@property,对外暴露统一的调用入口:
# Manager模型加属性 class Manager(models.Model): # 原有字段定义 ... @property def full_name(self): return f"{self.name.first_name} {self.name.last_name}" # TeamMember模型加属性 class TeamMember(models.Model): # 原有字段定义 ... @property def full_name(self): return f"{self.member.first_name} {self.member.last_name}"
封装后公共逻辑可以直接统一调用full_name属性,不需要额外传参:
def process_personnel(queryset): for item in queryset: name = item.full_name # 其余公共逻辑 ... # 调用时直接传QuerySet即可 process_personnel(Manager.objects.all()) process_personnel(TeamMember.objects.all())
这种方式适合业务中长期需要统一读取两类人员姓名的场景,后续所有调用都不需要再关心内部字段差异。
方式3:用operator.attrgetter做字段映射
如果不想写lambda也不想改模型,可以用attrgetter预定义字段路径,统一提取属性:
from operator import attrgetter def process_personnel(queryset, name_path): get_first = attrgetter(f"{name_path}.first_name") get_last = attrgetter(f"{name_path}.last_name") for item in queryset: name = f"{get_first(item)} {get_last(item)}" # 其余公共逻辑 ... # 调用时传入对应姓名的字段路径即可 process_personnel(Manager.objects.all(), "name") process_personnel(TeamMember.objects.all(), "member")
内容的提问来源于stack exchange,提问作者Chengzhi Yu
相关产品推荐
相关产品推荐

