Пользовательский декоратор Django для пользовательского разрешения

Существует модель Project с отношением ManyToMany к модели User, использующая таблицу соединений. Если пользователь не является участником проекта (не входит в таблицу соединений), я хочу запретить пользователю доступ к представлению, которое показывает конкретный проект.

Я знаю, что это можно решить с помощью простого оператора if внутри метода представления или пользовательского фильтра в шаблоне, но я хотел бы иметь возможность сделать это с помощью специального декоратора. Это возможно? Если да, то как это можно сделать?

Что-то типа:

def may_user_view_this(function):
    def wrapper(request, *args, **kwargs):
        user = request.user
        project = Project.objects.get(id=???????) #id
        if not project.has_user(user):
            return HttpResponse('You cannot view this.')
        else:
            return function(request, *args, **kwargs)
    return wrapper


@may_user_view_this() # if not go the specific url
def my_view(request, page_id=None):
    # do stuff and render

Как я могу получить доступ к параметру page_id, отправленному my_view из функции декоратора?


person user1121487    schedule 23.02.2013    source источник
comment
Да, это возможно.   -  person Pavel Anossov    schedule 23.02.2013


Ответы (1)


Конечно, это возможно, для этого и созданы декораторы.

person Brandon    schedule 23.02.2013
comment
И как это сделать? Мне нужно получить доступ к параметрам и т.д. - person user1121487; 23.02.2013
comment
Для начала неплохо было бы взглянуть на декоратор @login_required в Django. - person Brandon; 23.02.2013
comment
Ok. Я понимаю все, кроме; как получить параметр page_id внутри метода декоратора? - person user1121487; 23.02.2013
comment
Вы должны просто иметь возможность добавить аргумент page_id в свой декоратор. См.: artima.com/weblogs/viewpost.jsp?thread=240845 - person Brandon; 24.02.2013
comment
Да, это сработало. Это на самом деле очень хороший подход, я думаю. Даже лучше, чем предыдущие фильтры в Rails. Таким образом, я могу отправить проверенный объект Project обратно в метод представления в качестве аргумента, чтобы объект не приходилось искать дважды. - person user1121487; 24.02.2013
comment
Я пришел в Django из Rails, так что я определенно с вами согласен :) Я никогда не оглядывался назад. - person Brandon; 24.02.2013
comment
Я думаю, ты должен показать соответствующий пример, Брэндон. - person Shedrack; 04.05.2021
comment
@Shedrack оригинальный постер фактически предоставил свой собственный пример, плюс этому вопросу уже более 8 лет, и он освещается во многих источниках, таких как: pythonbasics.org/decorators - person Brandon; 04.05.2021