基于Django 2.0的员工自助应用:代理模型如何访问User用户名?
解决Django代理模型访问User实例属性的问题
你的代码里存在两个关键问题,导致无法正确访问username属性:
- 类定义阶段不能访问实例属性:你在
IDM类的类体里直接写了循环去获取groups,这时候super.username是完全错误的——类定义的时候还没有创建任何User/IDM实例,super在这里指向的是User类,而不是某个实例,自然没有username属性。 - 类属性会被所有实例共享:你把
groups定义成类属性,这意味着所有IDM实例都会共用同一个groups列表,这显然不是你想要的效果。
正确的实现方式
代理模型的核心是它的实例本质上就是原User模型的实例,所以你可以直接在实例方法/属性里用self.username来访问用户的username属性。我们可以把获取groups的逻辑改成实例属性(用@property装饰器),这样每次访问实例的groups时才会去IDM拉取最新数据:
from django.contrib.auth.models import User import idm from django.conf import settings class IDM(User): class Meta: proxy = True ordering = ('username', ) @property def groups(self): # 每次访问groups时初始化IDM客户端 idmclient = idm(settings.IDM_USER, settings.IDM_USER_PASS) groups_list = [] # 直接用self.username访问当前实例的用户名 idm_user = idmclient.getUser(samaccountname=self.username) for group in idm_user.get_groups(): groups_list.append(group.__dict__) return groups_list
为什么这样可行?
- 代理模型
IDM继承自User,所以每个IDM实例都拥有User模型的所有字段和方法,包括username,直接用self.username就能访问。 - 把
groups改成@property后,它成为了实例的动态属性,每个实例的groups都是独立获取的,不会互相干扰,而且每次访问都会获取最新的群组数据。
额外提示
如果你的IDM客户端初始化比较耗时,也可以把它改成懒加载或者缓存,避免每次访问groups都重新初始化客户端。另外要记住:代理模型不能添加新的数据库字段,只能扩展方法和改变模型的行为,这一点你的代码是符合要求的。
内容的提问来源于stack exchange,提问作者Phill93
相关产品推荐
相关产品推荐

