2012-08-29 102 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