这是模型:

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,以防止用户干扰其他人的对象。这包括编辑和删除每一个模型,我有,这是严重违反干燥原则。
有更好的办法吗?可能需要登录装饰器之类的东西?
编辑:
解决方案或多或少是简单的,正如泰尔萨博士在他的答案中所建议的,只有一点不同。我创建了继承CurUserOnly的基类object(我也想将这个类与DetailViewDeleteView一起使用),现在UpdateView继承CarDetailCurUserOnlyDetailView继承CarDeleteCurUserOnly等等。。。
有趣的是,我以前试过这个,但是没有成功,因为我忘记了python的MRO,DeleteView是继承列表中的第一个,DetailView应该是!
最后,这里是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

如果我有一个没有直接联系用户的模型,我需要做的就是添加CurUserOnly字段。例如,如果模型user_attribute的ForeignKey为Tyre则其DeleteView将如下所示:
class TyreDelete(CurUserOnly, DeleteView):
    model = models.Tyre
    user_attribute = 'car.user'

最佳答案

如何定义基类(或混合)和使用继承?

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

10-06 02:43