205 lines
9.6 KiB
Python
205 lines
9.6 KiB
Python
"""注释"""
|
||
from django.db import models
|
||
|
||
"""
|
||
输入 :当前用户实例(self)
|
||
输出 :包含所有下级用户的 扁平化列表 (多级结构被展开)
|
||
递归逻辑 :
|
||
先获取当前用户的直接下级(通过 self.subordinates.all())
|
||
对每个下级用户 递归调用自身,继续向下查找
|
||
合并所有结果到一个列表中
|
||
用户A
|
||
├─ 用户B
|
||
│ ├─ 用户C
|
||
│ └─ 用户D
|
||
└─ 用户E
|
||
|
||
[用户B, 用户C, 用户D, 用户E] # 按深度优先顺序
|
||
语法: wei = weiuser.objects.get(unionid="元宝零售")
|
||
print( wei.get_all_subordinates( ) )
|
||
结果: [<weiuser: weiuser object (oy4Jw6A1T3WkKOOhMxcbQTDSM8rs)>]
|
||
|
||
"""
|
||
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.JSONField(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"]
|