"""注释""" from django.db import models from uuid6 import uuid8 from wechat_数据库.雪花算法.雪花算法工具 import generator """ 输入 :当前用户实例(self) 输出 :包含所有下级用户的 扁平化列表 (多级结构被展开) 递归逻辑 : 先获取当前用户的直接下级(通过 self.subordinates.all()) 对每个下级用户 递归调用自身,继续向下查找 合并所有结果到一个列表中 用户A ├─ 用户B │ ├─ 用户C │ └─ 用户D └─ 用户E [用户B, 用户C, 用户D, 用户E] # 按深度优先顺序 语法: wei = weiuser.objects.get(unionid="元宝零售") print( wei.get_all_subordinates( ) ) 结果: [] """ defautl_img = ( "https://oss.fujugongxiang.com/six/%E7%A6%8F%E8%81%9A%E8%B4%A1%E7%BF%94%E5%B0%8F%E7%A8%8B%E5%BA%8F/home%E9%A1%B5%E9%9D%A2%E4%B8%BB%E5" "%9B%BE/%E5%A4%B4%E5%83%8F.png") from django.utils.translation import gettext_lazy models_app_name = "django_app" class weiuser用户角色表choicesStatus(models.TextChoices): """商家转账订单状态""" 推广员 = "推广员", gettext_lazy("推广员") 企微员工 = "企微员工", gettext_lazy("企微员工") 无状态 = "无状态", gettext_lazy("无状态") 普通会员 = "普通会员", gettext_lazy("普通会员") 六果科技有限公司 = "六果科技有限公司", gettext_lazy("六果科技有限公司") 群好友 = "群好友", gettext_lazy("群好友") class weiuser(models.Model): """用户基础信息表""" objects = models.Manager() # class ChoicesStatus(models.TextChoices): """商家转账订单状态""" 推广员 = "推广员", gettext_lazy("推广员") 企微员工 = "企微员工", gettext_lazy("企微员工") 无状态 = "无状态", gettext_lazy("无状态") unionid = models.CharField(primary_key=True, max_length=120) user_角色权限 = models.CharField(choices=weiuser用户角色表choicesStatus, default=weiuser用户角色表choicesStatus.普通会员) user_企微角色权限 = models.CharField(max_length=128, null=True, blank=True, ) mini_openid = models.CharField(max_length=100, db_comment="自身id", null=True, blank=True, unique=True) wechat_openid = models.CharField(max_length=100, db_comment="服务号自身id", null=True, blank=True, unique=True) wecom_openid = models.CharField(max_length=100, db_comment="企微自身id", null=True, blank=True, unique=True) external_userid = models.CharField(max_length=100, db_comment="外部联系人ID", null=True, blank=True, ) uesr_手机号码 = models.CharField(null=True, blank=True, ) user_昵称 = models.CharField(max_length=120, db_comment="用户的昵称", default="匿名用户") user_头像 = models.CharField(max_length=245, db_comment="用户头像", default="https://hudie.xiao.band/%E6%9C%AA%E5%91%BD%E5%90%8D.png") user_用户当前的等级 = models.IntegerField(default=1, ) # 自身的等级 user_省份 = models.CharField(max_length=128, null=True, blank=True, ) user_城市 = models.CharField(max_length=128, null=True, blank=True, ) user_区县 = models.CharField(max_length=128, null=True, blank=True, ) user_街道信息 = models.CharField(max_length=128, null=True, blank=True, ) user_绑定企微usrID账号 = models.CharField(max_length=128, null=True, blank=True, ) user_绑定企微UNIONID = models.CharField(max_length=128, null=True, blank=True, ) user_IP地址 = models.GenericIPAddressField(null=True, blank=True, ) user_绑定用工关系 = models.CharField(max_length=128, null=True, blank=True, ) codeConfigId = models.TextField(blank=True, null=True, ) # 企微的标签ID codeQrCode = models.TextField(blank=True, null=True, ) # 企微的二维码 codeRemark = models.TextField(blank=True, null=True, ) # 企微备注的信息 parent = models.ForeignKey(to="self", on_delete=models.SET_NULL, related_name="children", null=True, blank=True, ) # 模式:保护模式,有数据话是不能删除的; add_time = models.DateTimeField(null=True, blank=True, db_comment="用户添加好友的时间") dateAndTime = models.DateTimeField(auto_now_add=True, db_comment="创建时间") # 数据创建时间 updateTime = models.DateTimeField(auto_now=True, db_comment="更新时间") # 更新时间(需要用 save() ) class Meta: db_table = "weiuser" # 给数据表自定义一个名称;默认的会是在 应用名+类名 app_label = models_app_name ordering = ["-dateAndTime", "-updateTime"] def get_all_subordinates(self): """递归获取所有下级(包括间接下级)""" subs = [] for sub in self.children.all(): subs.append(sub) subs.extend(sub.get_all_subordinates()) return subs # ↓↓↓ 新增方法:获取所有上级(递归实现)↓↓↓ def get_all_superiors(self): """ 返回列表格式:[直接上级, 上上级, 上上上级...] """ superiors = [] # 递归终止条件:没有上级时停止 if self.parent: superiors.append(self.parent) # 递归获取上级的上级 superiors.extend(self.parent.get_all_superiors()) return superiors def get_nth_level_superior(self, n): """ 获取第n级上级 :param n: 上级层级 (1=直接上级, 2=上上级, 以此类推) :return: Weiuser对象或None """ """ 获取当前用户往上 n 级的父元素 :param n: 要查询的上级层级数 (必须 >=1) :return: weiuser 对象或 None (如果不存在) """ if n < 1: raise ValueError("n 必须大于或等于 1") current = self # 循环向上查询 n 次 for _ in range(n): if not current.parent: return None # 没有父级时提前终止 current = current.parent return current """ 这种实现方式更加简洁,但需要注意: 它使用了链式递归调用,可能会增加递归深度 每次递归都会重新检查字段是否存在,虽然安全但效率稍低 性能考虑 对于树形结构操作,递归实现通常更简洁,但在实际应用中需要注意: Python递归深度限制:默认1000层,可通过sys.setrecursionlimit()调整 性能开销:递归调用比循环有更高的开销 内存使用:递归会占用更多栈空间 在大多数实际应用中,树结构的深度不会超过100层,因此递归实现通常是可行的。但如果预期树结构会非常深(如超过1000层),建议使用循环实现或混合实现。 """ def find_ancestor_by_field(self, field_name, target_value, include_self=False): """ 从当前用户向上查找,找到第一个指定字段等于目标值的祖先 :param field_name: 要查找的字段名 :param target_value: 目标值 :param include_self: 是否包含自身 :return: Weiuser对象或None """ # 验证字段名是否有效 - 修复方法 if not hasattr(self, field_name): raise ValueError(f"无效字段名: {field_name}") # 如果包含自身且满足条件,直接返回 if include_self and getattr(self, field_name) == target_value: return self # 向上遍历祖先 current = self.parent while current: if getattr(current, field_name) == target_value: return current current = current.parent return None def find查找指定的上级(self, field_name, target_value, include_self=False): """ 从当前用户向上查找,找到第一个指定字段等于目标值的祖先 :param field_name: 要查找的字段名 :param target_value: 目标值 :param include_self: 是否包含自身 :return: Weiuser对象或None """ # 验证字段名是否有效 - 修复方法 if not hasattr(self, field_name): raise ValueError(f"无效字段名: {field_name}") # 如果包含自身且满足条件,直接返回 if include_self and getattr(self, field_name) == target_value: return self # 向上遍历祖先 current = self.parent while current: if getattr(current, field_name) == target_value: return current current = current.parent return None # class weiuser用户角色表(models.Model): # """城市信息表""" # objects = models.Manager() # # idKeyweiuser用户角色表 = models.UUIDField(primary_key=True, default=uuid8) # id_str = models.CharField(max_length=128, default=generator.generate_str) # user用户角色名称 = models.CharField(max_length=128, choices=weiuser用户角色表choicesStatus, # default=weiuser用户角色表choicesStatus.普通会员.value) # user用户的unionid = models.CharField(max_length=128, ) # dateAndTime = models.DateTimeField(auto_now_add=True, db_comment="创建时间") # 数据创建时间 # updateTime = models.DateTimeField(auto_now=True, db_comment="更新时间") # 更新时间(需要用 save() ) # # class Meta: # db_table = "weiuser用户角色表" # 给数据表自定义一个名称;默认的会是在 应用名+类名 # app_label = models_app_name # ordering = ["-dateAndTime", "-updateTime"]