Files

205 lines
9.6 KiB
Python
Raw Permalink Normal View History

2026-08-02 14:07:04 +08:00
"""注释"""
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() #
2026-08-21 23:48:29 +08:00
2026-08-02 14:07:04 +08:00
class ChoicesStatus(models.TextChoices):
"""商家转账订单状态"""
推广员 = "推广员", gettext_lazy("推广员")
企微员工 = "企微员工", gettext_lazy("企微员工")
无状态 = "无状态", gettext_lazy("无状态")
2026-08-21 23:48:29 +08:00
2026-08-02 14:07:04 +08:00
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, )
2026-08-21 23:48:29 +08:00
user_手机设备参数 = models.JSONField(null=True, blank=True, )
2026-08-02 14:07:04 +08:00
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() )
2026-08-21 23:48:29 +08:00
2026-08-02 14:07:04 +08:00
class Meta:
db_table = "weiuser" # 给数据表自定义一个名称;默认的会是在 应用名+类名
app_label = models_app_name
ordering = ["-dateAndTime", "-updateTime"]
2026-08-21 23:48:29 +08:00
2026-08-02 14:07:04 +08:00
def get_all_subordinates(self):
"""递归获取所有下级(包括间接下级)"""
subs = []
for sub in self.children.all():
subs.append(sub)
subs.extend(sub.get_all_subordinates())
return subs
2026-08-21 23:48:29 +08:00
2026-08-02 14:07:04 +08:00
# ↓↓↓ 新增方法:获取所有上级(递归实现)↓↓↓
def get_all_superiors(self):
"""
返回列表格式:[直接上级, 上上级, 上上上级...]
"""
superiors = []
# 递归终止条件:没有上级时停止
if self.parent:
superiors.append(self.parent)
# 递归获取上级的上级
superiors.extend(self.parent.get_all_superiors())
return superiors
2026-08-21 23:48:29 +08:00
2026-08-02 14:07:04 +08:00
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")
2026-08-21 23:48:29 +08:00
2026-08-02 14:07:04 +08:00
current = self
# 循环向上查询 n 次
for _ in range(n):
if not current.parent:
return None # 没有父级时提前终止
current = current.parent
return current
2026-08-21 23:48:29 +08:00
2026-08-02 14:07:04 +08:00
"""
这种实现方式更加简洁,但需要注意:
它使用了链式递归调用,可能会增加递归深度
每次递归都会重新检查字段是否存在,虽然安全但效率稍低
性能考虑
对于树形结构操作,递归实现通常更简洁,但在实际应用中需要注意:
Python递归深度限制:默认1000层,可通过sys.setrecursionlimit()调整
性能开销:递归调用比循环有更高的开销
内存使用:递归会占用更多栈空间
在大多数实际应用中,树结构的深度不会超过100层,因此递归实现通常是可行的。但如果预期树结构会非常深(如超过1000层),建议使用循环实现或混合实现。
"""
2026-08-21 23:48:29 +08:00
2026-08-02 14:07:04 +08:00
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}")
2026-08-21 23:48:29 +08:00
2026-08-02 14:07:04 +08:00
# 如果包含自身且满足条件,直接返回
if include_self and getattr(self, field_name) == target_value:
return self
2026-08-21 23:48:29 +08:00
2026-08-02 14:07:04 +08:00
# 向上遍历祖先
current = self.parent
while current:
if getattr(current, field_name) == target_value:
return current
current = current.parent
return None
2026-08-21 23:48:29 +08:00
2026-08-02 14:07:04 +08:00
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}")
2026-08-21 23:48:29 +08:00
2026-08-02 14:07:04 +08:00
# 如果包含自身且满足条件,直接返回
if include_self and getattr(self, field_name) == target_value:
return self
2026-08-21 23:48:29 +08:00
2026-08-02 14:07:04 +08:00
# 向上遍历祖先
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"]