我们正在针对同一个数据库运行多个 django 站点(我们称它们为 site1、site2、site3),并且我们希望允许它们之间存在重复的用户名。Site 和 auth 框架似乎没有实现这一点,默认情况下,username 是 auth.User 中的唯一字段。
所以到目前为止我所做的(猴子补丁,搞砸了用户对象......):
User._meta.get_field('username')._unique = False
User.add_to_class('site', models.ForeignKey(Site, default=Site.objects.get_current().id, blank=True, null=True))
User._meta.unique_together = (('username', 'site'),)
这件作品去掉了用户名的唯一性,增加了一个站点字段,使夫妇(用户名,站点)唯一。
如果某些用户在不同站点上具有相同的用户名,那么在请求 User.objects.get(username=xx) (例如,身份验证后端)时可能会出现问题。所以,我决定修补 User.objects 管理器:
def get_query_set(filter=True):
q = QuerySet(User.objects.model, using=User.objects._db)
if filter:
return q.filter(site = Site.objects.get_current())
return q
User.objects.get_query_set = get_query_set
到目前为止似乎工作。但是......站点使用几乎相同的对象,很可能我们使用管理界面更改这些对象的用户字段,这对所有站点都是通用的......因此,如果我想为一个对象(它有auh.User 的外键)到 site2 的用户,同时在 site1 上以管理员身份登录,这是行不通的,因为用户管理器将在 site=site1 上过滤。
我挖了一下,发现这似乎有效:
class UserDefaultManager(UserManager):
def get_query_set(self, filter=None):
return QuerySet(User.objects.model)
User._default_manager = UserDefaultManager()
据我了解, _default_manager 由相关的对象管理器使用。然后, User.objects.get(username=xx) 过滤网站,而 an_object.user 不会。
好吧,问题是:是的,这很混乱,我很确定会有缺陷,但它们是什么?
下一个问题是:如果它是有效的,那么放置这段代码的最佳位置在哪里?它当前位于 models.py 文件中,只是在加载模块时运行...