2011-10-21 37 views
1

這是模型:Django的 - 對象級別premission和基於類的通用視圖

class Car(models.Model): 
    user = models.ForeignKey(User, related_name='cars') 
    name = models.CharField(max_length=64) 

網址模式是這樣的:

url(r'^car/(?P<pk>\d+)/$', login_required(CarDetails.as_view()), name='car_details) 

,並查看:

class CarDetail(DetailView): 
    context_object_name = 'car' 
    template_name = 'my_app/car_details.html' 
    model = models.Car 

    def get_object(self, *args, **kwargs): 
     car = super(CarDetail, self).get_object(*args, **kwargs) 
     if car.user != self.request.user: 
      raise PermissionDenied() 
     else: 
      return car 

這工作正常,但在每個班級中,我必須重寫get_object以防止用戶亂用別人的對象。這包括我對每個型號的編輯和刪除,這是嚴重違反DRY原則。

有沒有更好的方法來做到這一點?像login_required裝飾器可能嗎?

編輯

溶液更多或更少的簡單DrTyrsa在他的回答提出一個差別不大。我創建的基類CurUserOnly繼承object,而不是DetailView(我想使用這個類​​和UpdateView,太),現在CarDetail繼承CurUserOnlyDetailViewCarDelete繼承CurUserOnly和​​等等......

滑稽事情是,我以前試過,但它沒有工作,因爲我忘記了蟒蛇的MRO和DetailView第一次在繼承名單CurUserOnly應該是!

最後,這裏是CurUserOnly類:

class CurUserOnly(object): 
    def get_object(self, *args, **kwargs): 
     obj = super(CurUserOnly, self).get_object(*args, **kwargs) 
     user_attribute = getattr(self, 'user_attribute', 'user') 
     user = obj 
     for part in user_attribute.split('.'): 
      user = getattr(user, part, None) 
     if user != self.request.user: 
      raise PermissionDenied() 
     else: 
      return obj 

如果我有沒有直接接觸到用戶模型中的所有我需要做的就是添加user_attribute場。舉例來說,如果我有ForeignKey的到Car模型Tyre其DeleteView應該是這樣的:

class TyreDelete(CurUserOnly, DeleteView): 
    model = models.Tyre 
    user_attribute = 'car.user' 

回答

3

約definig基類(或混入),並使用繼承什麼?

class CurUserOnlyDetailView(DetailView): 
    def get_object(self, *args, **kwargs): 
     obj = super(CurUserOnlyDetailView, self).get_object(*args, **kwargs) 
     if obj.user != self.request.user: 
      raise PermissionDenied() 
     else: 
      return obj 

class CarDetail(CurUserOnlyDetailView): 
    context_object_name = 'car' 
    template_name = 'my_app/car_details.html' 
    model = models.Car 

# another view, no DRY violation 
class BikeDetail(CurUserOnlyDetailView): 
    context_object_name = 'bike' 
    template_name = 'my_app/bike_details.html' 
    model = models.Bike 
+0

不是我所需要的,但給了我正確的想法,並解決了我的一個小差異的問題。我補充說明問題。 –

相關問題