2015-05-06 69 views
2

我正在製作一個基本的應用程序來教初學者。每個用戶都可以寫筆記,但是我想讓用戶無法查看或更新其他用戶的筆記。在Django CBV中檢查403的位置?

我有以下看法,但我不得不重複自己。

from django.core.exceptions import PermissionDenied 

... 

class NoteUpdate(LoginRequiredMixin, UpdateView): 

    ... 

    def get(self, request, *args, **kwargs): 
     self.object = self.get_object() 

     if self.object.owner != self.request.user: 
      raise PermissionDenied 

     return super(NoteUpdate, self).get(request, *args, **kwargs) 

    def post(self, request, *args, **kwargs): 
     self.object = self.get_object() 

     if self.object.owner != self.request.user: 
      raise PermissionDenied 

     return super(NoteUpdate, self).post(request, *args, **kwargs) 

我覺得可能有一種方法可以做到這一點,而無需重複自己。是的,我可以寫一個方法,像這樣和來自調用它:

def check_permission(self): 
    if self.object.owner != self.request.user: 
     raise PermissionDenied 

但我真正的意思是我在重寫了錯誤的方法呢?有沒有更傳統的方式來做到這一點?感覺有點怪異壓倒一切的獲得()和。員額()

回答

3

要回答你的問題:重寫.get().post()是好的,因爲安全性和完整性的原因,你會想你都和get()意見post()之前驗證顯示和特別是修改數據。現在,如果你想在重構GET或POST這樣做,有兩個簡單的這樣做的方法:

小學(模型法):

models.py

class Model(models.Model): 
    owner = models.ForeignKey(User) 
    ... 

    def deny_if_not_owner(self, user): 
     if self.owner != user: 
      raise PermissionDenied 
     return self.owner 

views.py

class NoteUpdate(LoginRequiredMixin, UpdateView): 
    ... 

    def get(self, request, *args, **kwargs): 
     self.object = self.get_object() 

     self.object.deny_if_not_owner(request.user) 

     return super(NoteUpdate, self).get(request, *args, **kwargs) 

    def post(self, request, *args, **kwargs): 
     self.object = self.get_object() 

     self.object.deny_if_not_owner(request.user) 

     return super(NoteUpdate, self).post(request, *args, **kwargs) 

///////

替代(密新):

如果您看到自己今後再次使用此驗證,則創建Mixin可讓您輕鬆地將此代碼添加到許多類中。

class DenyWrongUserMixin(object): 
    def get(self): 
     if self.object.owner != self.request.user: 
      raise PermissionDenied 
     return super(DenyWrongUserMixin, self).get(*args, **kwargs) 

    def post(self): 
     if self.object.owner != self.request.user: 
      raise PermissionDenied 
     return super(DenyWrongUserMixin, self).post(*args, **kwargs) 

然後:

class NoteUpdate(LoginRequiredMixin, DenyWrongUserMixin, UpdateView): 

    ... 

    def get(self, request, *args, **kwargs): 
     ... 

    def post(self, request, *args, **kwargs): 
     ... 
+0

我以爲你想重構可擴展的使用。我更新了我的答案,直接回答你的問題:「重寫'get'和'post'正確 - 我的答案是肯定的。你可以看到我的修改答案,看看爲什麼,主要解決方案顯示如何將一些驗證模型級別減少視圖中的代碼,同時允許稍後輕鬆實現。 – Hybrid

+0

感謝您的更新答案。這是一個很好的提醒,關於製作厚模型和薄視圖,雖然它確實會讓我錯誤地將HTTP響應內容放入模型(我刪除了我以前的評論,因爲它不適用於你對mixin的新評論,儘管現在我看到你回覆了它,對不起!)。 – user3827132

0

可以重寫get方法或get_queryset方法。如果登錄用戶不是所有者,則get_queryset將引發404。

def get_queryset(self): 
    qs = super(NoteUpdate, self).get_queryset() 
    return qs.filter(owner=self.request.user) 

或者你可以重寫get方法,因爲它會被稱爲先提高PermissionDenied,所以沒有理由重寫後的方法爲好。

def get(self, request, *args, **kwargs): 
    self.object = self.get_object() 
    if self.object.owner != self.request.user: 
     raise PermissionDenied 
    return super(NoteUpdate, self).get(request, *args, **kwargs) 

然後,您可以創建一個mixin並從mixin擴展您的視圖以避免重複。

+0

如果我重寫GET但不覆蓋POST我明白我會防範意外(因爲他們無法通過網頁查看錶單頁面),但是有人仍然是惡意的嗎? – user3827132