Обертывание / оформление функции в URL-адресах.py vs в views.py

#django #decorator

#django #декоратор

Вопрос:

Итак, я довольно хорошо знаком с переносом функций в views.py . Итак, я написал декоратор для перенаправления на REDIRECT_URL по умолчанию, если пользователь вошел в систему (что-то вроде обратного login_required ); это основано на том, как я создавал представления в прошлом:

 def not_logged_in(redirect_url=None, redirect_field_name=REDIRECT_FIELD_NAME):
    def decorator(view_func, *args, **kwargs):
        def wrapper(request, *args, **kwargs):
            if not request.user.is_authenticated():
                return view_func(*args, **kwargs)
            else:
                redirect_url = (request.REQUEST.get(redirect_field_name, redirect_url) or
                                settings.REDIRECT_URL)
                return HttpResponseRedirect(redirect_url)
        return wrapper
    return decorator
  

Однако я получаю следующую ошибку: 'function' object has no attribute 'status_code' которая вызвана промежуточным программным обеспечением, ожидающим HttpResponse. Когда я смотрю на значение для response , я вижу, что это <function wrapper at 0x2b3a9922a500> .

Вот как я вызываю это в urls.py :

 url(r'login/', 
     not_logged_in(auth_views.login), 
     {'authentication_form': LoginForm },
),
  

Комментарии:

1. Ваша проблема в том, что ваш декоратор не используется. Вместо этого вы возвращаете функцию <decorator> ко url() второму аргументу. Ваш декоратор кажется нормальным, но вы должны использовать его следующим образом: not_logged_in(<your arguments>)(<view callable>)

Ответ №1:

Вот моя реализация того же самого.

 def logout_required(view):
    def f(request, *args, **kwargs):
        if request.user.is_anonymous():
            return view(request, *args, **kwargs)
        return HttpResponseRedirect(settings.LOGIN_REDIRECT_URL)
    return f
  

В urls.py :

 urlpatterns = patterns("",
    url(r"^login/", logout_required(login), {"template_name": "users/login.html"}, "login"),
    # ...
  

Я надеюсь, что это поможет (хотя и не уверен).

Ответ №2:

Первым аргументом для декоратора должна быть функция, которую необходимо оформить.

 def not_logged_in(func, redirect_url=None, redirect_field_name=REDIRECT_FIELD_NAME):
  

Функция декоратора также не нужна. Возвращает функцию-оболочку из not_logged_in.

Ответ №3:

То, как вы реализовали свой декоратор, является параметризованным и, следовательно, вызываемым: вот почему у вас есть дополнительный уровень функции, который, как ошибочно утверждает fizixx, не требуется. Вам нужно сначала вызвать внешнюю оболочку, чтобы вернуть фактически оформленную функцию. Итак, что-то вроде:

 url(r'login/', 
 not_logged_in(auth_views.login)('/redirect/', 'redirect_field'), 
 {'authentication_form': LoginForm },
),
  

Комментарии:

1. Хммм … это тоже не работает. Я думаю, единственное, что мне никогда не было ясно с декораторами, это сколько вложенных функций требуется или почему.