这是模型:
class Car(models.Model):
user = models.ForeignKey(User, related_name='cars')
name = models.CharField(max_length=64)
Url模式是这样的:
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 decorator那样的东西可能吗?
修改:
DrTyrsa在答案中提出的解决方案或多或少都很简单,只有一点点不同。我创建了继承CurUserOnly
而不是object
的基类DetailView
(我想将此类与DeleteView
和UpdateView
一起使用)现在{{ 1}}继承CarDetail
和CurUserOnly
,DetailView
继承CarDelete
和CurUserOnly
等等......
有趣的是我之前尝试过这个,但它没有用,因为我忘记了python的MRO,DeleteView
在DetailView
应该是继承列表中的第一个!{/ p>
最后,这里是CurUserOnly
class:
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
字段。例如,如果我将带有ForeignKey的模型user_attribute
发送到Tyre
,则其DeleteView将如下所示:
Car
答案 0 :(得分:4)
如何定义基类(或混合)和使用继承?
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