35

カスタム オブジェクト モデル マネージャーを上書きして、特定のユーザーが作成したオブジェクトのみを返すようにしたいと考えています。管理者ユーザーは、オブジェクト モデル マネージャーを使用してすべてのオブジェクトを返す必要があります。

今、私はうまくいく可能性のあるアプローチを見つけました。彼らは、次のような独自のミドルウェアを作成することを提案しています。

#### myproject/middleware/threadlocals.py

try:
    from threading import local
except ImportError:
    # Python 2.3 compatibility
    from django.utils._threading_local import local

_thread_locals = local()

def get_current_user():
    return getattr(_thread_locals, 'user', None)

class ThreadLocals(object):
    """Middleware that gets various objects from the
    request object and saves them in thread local storage."""
    def process_request(self, request):
        _thread_locals.user = getattr(request, 'user', None)

#### end

また、カスタム マネージャーでは、get_current_user()メソッドを呼び出して、特定のユーザーが作成したオブジェクトのみを返すことができます。

class UserContactManager(models.Manager):
    def get_query_set(self):
        return super(UserContactManager, self).get_query_set().filter(creator=get_current_user())

これは、このユースケースに対する適切なアプローチですか? これは機能しますか?それとも「大槌で木の実を割る」ようなものですか?;-)

ちょうど使用:

Contact.objects.filter(created_by= user)

それぞれのビューでは、私にはあまりきれいに見えません。

編集このミドルウェアアプローチを使用しないでください!!!

以下のJack M.が述べたアプローチを使用してください

しばらくテストした後、このアプローチは非常に奇妙に動作し、このアプローチではグローバル状態と現在のリクエストを混同します。

以下に示すアプローチを使用します。とても簡単で、ミドルウェアをいじる必要はありません。

現在のユーザーまたは他のユーザーを入力として期待する関数を使用して、モデルにカスタム マネージャーを作成します。

#in your models.py
class HourRecordManager(models.Manager):
    def for_user(self, user):
        return self.get_query_set().filter(created_by=user)

class HourRecord(models.Model):
    #Managers
    objects = HourRecordManager()

#in vour view you can call the manager like this and get returned only the objects from the currently logged-in user.

hr_set = HourRecord.objects.for_user(request.user)

ミドルウェア アプローチに関するこのディスカッションも参照してください。

4

3 に答える 3

57

これを処理する 1 つの方法は、 を再定義する代わりに新しいメソッドを作成することget_query_setです。次のようなもの:

class UserContactManager(models.Manager):
    def for_user(self, user):
        return super(UserContactManager, self).get_query_set().filter(creator=user)

class UserContact(models.Model):
    [...]
    objects = UserContactManager()

これにより、ビューは次のようになります。

contacts = Contact.objects.for_user(request.user)

これにより、ビューをシンプルに保つことができます。また、Django の組み込み機能を使用するため、将来的に壊れることはありません。

于 2010-01-29T16:15:56.117 に答える
6

ユーザー情報を格納するには、ミドルウェアを使用する必要があるようです。

ただし、デフォルトの ModelManager を変更するのではなく、オブジェクトの代わりにobjectsコードで使用する別のマネージャーにフックします。user_objects

これはビュー内でのみ使用するため@login_required、ミドルウェアで複雑なエラー処理をすべて行う必要はありません。

ちょうど私の2¢。

于 2010-01-05T13:55:19.577 に答える