сделать декоратором Только создатель контента может манипулировать им

#python #django #decorator

Вопрос:

Я создал два декоратора, чтобы заблокировать любому доступ к определенному контенту, например:

    @method_decorator(login_required(login_url='core:login'), name='dispatch')
   @method_decorator(allowed_users(allowed_roles=['writer']), name='dispatch')
    class BookDeleteView(BSModalDeleteView):
        model = Book
        template_name = 'book/book_delete.html'
        success_message = 'Success: book was deleted.'
        success_url = reverse_lazy('core:book_list')
 

я хочу создать декоратора, который выглядит так

 book=Book.objects.get(id=pk)
if request.user==book.writer.profile.user:
 

Ответ №1:

Если вы хотите использовать декоратора:

 def writers_only(function):
  @wraps(function)
  def wrap(request, *args, **kwargs):
        if request.user == Book.objects.get(id=kwargs.get('pk')).writer.profile.user:
            return function(request, *args, **kwargs)
        else:
            # Do something else 
  return wrap
 

Затем добавьте это в представление на основе классов:

 # Other decorators
@method_decorator(writers_only, name='dispatch')
class BookDeleteView(BSModalDeleteView):
    # Your code
 

В противном случае вы также можете переопределить BookDeleteView.get_object (вы можете создать микс для повторного использования этой реализации get_object в различных представлениях):

 @method_decorator(login_required(login_url='core:login'), name='dispatch')
@method_decorator(allowed_users(allowed_roles=['writer']), name='dispatch')
    class BookDeleteView(BSModalDeleteView):
        model = Book
        template_name = 'book/book_delete.html'
        success_message = 'Success: book was deleted.'
        success_url = reverse_lazy('core:book_list')
        
        def get_object(self, *args, **kwargs):
            obj = super().get_object(*args, **kwargs)
            if obj.writer.profile.user != self.request.user:
                raise PermissionDenied() # Or do something else
            return obj
 

Ответ №2:

Для этого вам не нужен декоратор. То, что вам нужно queryset , определено в вашем представлении модели, которое будет ограничивать запрос:

 class BookDeleteView(BSModalDeleteView):
    def get_queryset(self):        
        return self.model.objects.filter(user=self.request.user)
 

В случае, если это необходимо сделать только для удаления, вы также можете установить его динамически в зависимости от запроса:

 class BookDeleteView(BSModalDeleteView):
    def get_queryset(self):
        if self.request.method == 'DELETE':        
            return self.model.objects.filter(user=self.request.user)
        return self.model.objects.all()