2016-07-23 17 views
2

私はPostというモデルを持ち、ownerUserへの外部キー)と呼ばれるフィールドを持っています。もちろん、所有者だけがupdateまたはdeleteの投稿を投稿することができます。言われて、私は、ユーザーがログインしているが、その後、私はまたupdate/deleteに質問をしようとするユーザーがownerであることを確認する必要があることを確認するビューでlogin_requiredデコレータを使用することをDjango:DRY原則とUserPassesTestMixin

私はドキュメントDjango: Generic Editing Viewsを使用していたように、私はDjango: UserPassesTestMixinを使用する必要があると言います。

この検証はupdatedeleteビューのために行われます。ドライ、これについてどうやって行くの?私はTestUserOwnerOfPostという名前のクラスを作成し、test_func()を作成し、updatedeleteビューはそれから継承させる必要がありますか?すべてのは、ログインユーザがシステムに上記のコードでは

from django.views.generic.edit import UpdateView 
from django.contrib.auth.decorators import login_required 
from django.contrib.auth.mixins import UserPassesTestMixin 

class TestUserOwnerOfPost(UserPassesTestMixin):       
    def test_func(self):              
     return self.request.user == self.post.owner 

class EditPost(UpdateView, TestUserOwnerOfPost):       
    model = Post                   
    @method_decorator(login_required)           
    def dispatch(self, *args, **kwargs):          
     return super(EditPost, self).dispatch(*args, **kwargs) 

、できるedit/delete任意のポスト:私が試してみましたし、うまくいきませんでした何

原因、以下のコード。私は間違って何をしていますか?私は何かを欠いている?ありがとう。

答えて

4

最初の問題は@rafalmpが言うように、あなたが継承するクラスの順序は、間違っているということです。

しかし、UserPassesTestミックスインビューを実行前にテストを実行するため、問題を解決しない定着。つまり、self.objectはまだ設定されていないため、self.objectのオーナーを確認するのは実際には適していません。アイム・ビューが今までself.postを設定していることはないと思うが、私はそれについて間違っているかもしれない - 私はself.object代わりのself.postを使用しています注意してください。

1つのオプションは、テスト関数の内部でself.get_object()を呼び出すことです。ビューはオブジェクトを2回フェッチするため、これは少し非効率ですが、実際は問題ではないでしょう。

def test_func(self): 
    self.object = self.get_object() 
    return self.request.user == self.object.owner 

別のアプローチは、ユーザが所有するオブジェクトにそれを制限するために、get_querysetをオーバーライドすることです。つまり、オブジェクトを所有していない場合、404エラーが発生します。この動作は、ログインページにリダイレクトされるUserPassesTestMixinとまったく同じ動作ではありませんが、問題ありません。

class OwnerQuerysetMixin(object):       
    def get_queryset(self): 
     queryset = super(OwnerQuerysetMixin, self).get_queryset()             
     # perhaps handle the case where user is not authenticated 
     queryset = queryset.filter(owner=self.request.user) 
     return queryset 
+0

あなたの詳細な説明をいただき、ありがとうございます。そして私には、オブジェクトがユーザーが所有するものに制限するのが理にかなっています。ただ一つの簡単な質問です。これがうまくいくためには、 'UpdateView'の前に' OwnerQuerysetMixin'を継承する必要があります。何故ですか?私は 'get_queryset'は' UpdateView'からのメソッドであり、 'OwnerQuerysetMixin'のメソッドでその考え方を上書きするべきだと思っていました。(私が何か不足していると私を赦してください)' OwnerQuerysetMixin'を継承する方が意味があります。 'UpdateView'の後に。一言、私はちょうど相続物がここでどのように働くかについて明確にしたい。 – gglasses

+1

[この質問](http://stackoverflow.com/questions/10018757/how-does-the-order-of-mixins-affect-the-ivedived-class)注文を理解するのに役立つかもしれません。 – Alasdair

2

あなたが問題を継承するクラスの順。 UpdateViewが実行される前に、仕事へのアクセス制御のために、それが施行されている必要があります

class EditPost(TestUserOwnerOfPost, UpdateView): 
+0

実際、その後私は、 '「はAttributeErrorを:EditPost」取得オブジェクトには属性「post''を持っていない:UpdateViewは実際にオブジェクト' POST'を取得するオブジェクトであるため、/ – gglasses

+0

まあ、私は実際にこれがあり得ます私は 'TestUserOwnerOfPost'を最初にインポートしています。問題は、どのように私の検証を達成することができますか? – gglasses