4

同じデータベースに対して複数の django サイト (サイト 1、サイト 2、サイト 3 と呼びましょう) を実行しており、サイト全体でユーザー名の重複を許可したいと考えています。サイトと認証フレームワークはこれを達成していないようです。デフォルトでは、ユーザー名は 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 ファイルにあり、モジュールがロードされたときに実行されました...

4

1 に答える 1

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

次に、デコレーターを追加する各ビューで、ユーザーがこのサイトへの接続を許可されていない場合、http403 エラーが発生します。

于 2012-08-29T09:46:55.227 に答える