2012-08-29 52 views
3

我们对同一个数据库运行多个django网站(让我们称它们为site1,site2,site3),并且我们希望允许重复的用户名相互关联。 网站和身份验证框架似乎并未达到此目的,默认情况下,用户名是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(用户名= 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 

似乎工作至今。但是......这些网站使用的是几乎相同的对象,并且很可能我们使用管理界面来更改这些对象的用户字段,这对所有网站都是常见的......因此,如果我想要将对象(它具有一个foreignkey到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(用户名= xx)过滤器,而an_object.user不会。

嗯,问题是:是的,这是混乱的,我很确定会有缺陷,但是它们是哪一个?

接下来的问题是:如果它是有效的,那么放这段代码的最佳位置在哪里?这是目前在一个models.py文件,刚跑作为模块加载...

+0

保存哪些网站的用户名有效并且在身份验证过程中检查此列表是否简单?通过这种方式,您可以为不同站点上的用户提供重用登录的功能,就像Stack Exchange一样。 –

+0

其他方法会更简单__messy__更少,但如果你真的想使用这个,那么你应该创建一个__manager.py__文件 – BlueMagma

+0

这个问题是否给你提供了一些建议? http://stackoverflow.com/questions/4662348/implementing-single-sign-on-sso-using-django – Pramod

回答

2

取而代之的是我建议使用一个配置文件:

models.py:

from django.contrib.auth.models import User 


class UserProfile(models.Model): 
    """ Modèle ajoutant des propriété au modèle User """ 
    user = models.OneToOneField(User, editable=False) 
    site1 = models.BooleanField() 
    site2 = models.BooleanField() 
    site3 = models.BooleanField() 


def create_user_profile(sender, instance, created, **kwargs): 
    """ Crée la jonction entre le modèle User, et le modèle UserProfile """ 
    if created: 
     UserProfile.objects.create(user=instance) 

post_save.connect(create_user_profile, sender=User) 

和每个站点创建一个装饰:

decorators.py:

try: 
    from functools import wraps 
except ImportError: 
    from django.utils.functional import wraps 
from django.http import HttpResponseForbidden 
from django.contrib.auth.decorators import login_required 
from distrib.views.error import error403 


def site1_required(function): 
    @wraps(function) 
    @login_required 
    def decorateur(request, *k, **a): 
     if request.user.get_profile().site1 or request.user.is_superuser: 
      return function(request, *k, **a) 
     else: 
      result = error403(request) 
      return HttpResponseForbidden(result) 
    return decorateur 
    return function 

然后在每个视图ÿ ou添加修饰器,如果用户不允许在这个站点上连接,他会得到一个http403错误。

+0

正如我上面评论的那样,我想我会回滚到类似的地方,不会搞乱auth.user模型,在我的用户配置文件中添加一个manytomanyfield(Site),并在登录/注册信号中添加一些连接,以在用户重新使用用户名时捕捉/重定向用户。谢谢所有:) – fylb