这是模型: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
继承CurUserOnly
和DetailView
,CarDelete
继承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'
不是我所需要的,但给了我正确的想法,并解决了我的一个小差异的问题。我补充说明问题。 –