0

プリントの to_publish 属性が True に設定されている場合は、プリントの所有者のみ、または誰でもアクセスできるようにしたい PrintDetailView があります。

これを行うためにpermission_required()、Print モデルから callable を受け入れるメソッド デコレーターを使用しようとしています。

class PrintDetailView(DetailView):
    template_name = 'prints/detail.html'
    queryset = Print.objects.all()

    @method_decorator(permission_required('prints.user_is_owner_or_public'))
    def dispatch(self, request, *args, **kwargs):    
        return super(PrintDetailView, self).dispatch(request, *args, **kwargs)

Print モデルのuser_is_owner_or_public()メソッドは次のとおりです。

def user_is_owner_or_public(self, user):
        """Checks whether the print is a public print, or
        whether the current user is the owner
        """
        if self.user is user or self.to_publish:
            return True

ここで、to_publish 属性が True に設定されている印刷詳細ページでこれをテストすると、まだログイン画面が表示されるので、permission_required() 関数が呼び出されていることがわかります。ただし、明らかに user_is_owner_or_public() メソッドを呼び出していません。

誰かが私がこれをどのように機能させるかを理解してもらえますか?

ティア、アンディ

4

1 に答える 1

2

これpermission_requiredpermission_required、Django パーミッション システムの一部であり、Django がパーミッション データベース テーブルをチェックして、ログインしているユーザーの適切な名前のパーミッション オブジェクト (直接付与されるか、グループを介して付与される) をチェックする原因となります。あなたがやろうとしていることは、周りのデコレータの範囲外ですdispatch- 他に何もなければ、あなたの印刷インスタンスはビューの後半までロードされないので、チェックすることはできませんto_publish.

get_querysetこれを処理する最も簡単な方法は、ビューでメソッドを定義することです。

from django.db.models import Q

class PrintDetailView(DetailView):
    template_name = 'prints/detail.html'

    def get_queryset(self):
        return Print.objects.filter(Q(user=self.request.user) | Q(to_publish=True))

これにより、ユーザーが見ることができない印刷物に対して 404 がスローされます。ログインページにリダイレクトしたい場合は、getメソッドをオーバーライドする必要があります。

from django.conf import settings
from django.shortcuts import redirect

class PrintDetailView(DetailView):
    template_name = 'prints/detail.html'

    def get(self, request, *args, **kwargs):
        self.object = self.get_object()
        if not(self.object.to_publish or self.object.user == request.user):
            return redirect(settings.LOGIN_URL) # or a login viewname
        else:
            context = self.get_context_data(object=self.object)
            return self.render_to_response(context)

余談ですが、user_passes_testデコレーターを使用して、ディスパッチ メソッドに制限を追加できます (ユーザー オブジェクトからのみ決定できる場合)。ここでは役に立ちませんが、テストでユーザーのみが必要で、印刷インスタンスが必要ない場合は必要です。

于 2013-09-04T22:34:37.667 に答える