2011-10-21 42 views
1

これはモデルです:ジャンゴ - オブジェクトレベルの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でこのクラスを使用していた)の代わりにDetailViewobjectを継承し、基本クラスCurUserOnlyを作成し、今CarDetailCurUserOnlyDetailViewを継承し、CarDeleteCurUserOnlyと​​を継承し、問題は私がこれを前に試したことですが、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' 

答えて

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

私は必要なものではありませんが、私に正しいアイデアを与え、少しの違いで問題を解決しました。私は質問に明確化を加えました。 –

関連する問題