これはモデルです:ジャンゴ - オブジェクトレベルのpremissionとクラスベースの汎用ビュー
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
この
class Car(models.Model):
user = models.ForeignKey(User, related_name='cars')
name = models.CharField(max_length=64)
URLパターンは、このような何かを行きます問題なく動作しますが、すべてのクラスで、ユーザが他人のオブジェクトを混乱させるのを防ぐために、get_object
をオーバーライドする必要があります。これには、私が持っているすべてのモデルの編集と削除が含まれます。これはDRY原則に重大な違反です。
これを行うより良い方法はありますか? login_requiredデコレータのようなものかもしれない?
EDIT:
ソリューションDrTyrsaは一つの小さな違いが、彼の答えで提案されているように、多かれ少なかれ簡単でした。私がおかしい...ように
を(私も、とUpdateView
でこのクラスを使用していた)の代わりにDetailView
のobject
を継承し、基本クラスCurUserOnly
を作成し、今CarDetail
CurUserOnly
とDetailView
を継承し、CarDelete
はCurUserOnly
とを継承し、問題は私がこれを前に試したことですが、CurUserOnly
があれば、私はPythonのMROを忘れてしまい、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
そして、私は、ユーザーへの直接接触を持っていないモデルを持っている場合、私がする必要があるすべては、user_attribute
フィールドを追加しています。私はCar
へのForeignKeyを持つモデルTyre
を持っている場合たとえば、そのDeleteViewは次のようになります。
class TyreDelete(CurUserOnly, DeleteView):
model = models.Tyre
user_attribute = 'car.user'
私は必要なものではありませんが、私に正しいアイデアを与え、少しの違いで問題を解決しました。私は質問に明確化を加えました。 –