Персонализиран декоратор на 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
Добре. Схващам всичко освен; как да получа параметъра 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