2011-10-21 38 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

不是我所需要的,但给了我正确的想法,并解决了我的一个小差异的问题。我补充说明问题。 –

相关问题