In a (FBV) view I'm trying to pass a function in to the login_required decorator. My function is called 'is_login_needed' and I want the login_required decorator to effectively switch itself off if login is not needed.
The scenario is on-line training and if the training instruction has questions with scores then obviously the user needs to login. On the other hand if it is simply a demonstration video or plain blah with no questions/answers/scores it should be viewable by anyone whether they are logged in or not.
My function goes like this and the docstring reveals my understanding ...
def is_login_needed(user):
""" the login_required decorator has a user_passes_test() function as
its first arg. If it returns True, no login is required. user.login_here
is always set equal to the selected course.login_needed. For courses
needing a login, self.is_authenticated must be True. For courses not
needing a login, self.is_authenticated may return anything but this
function passed to the login_required decorator must return True
"""
if not user.login_here:
return True
So the problem is that manage.py runserver reports an attribute error saying the function (presumably mine) does not have an attribute 'user' ... like this ...
<earlier runserver traceback lines snipped> File "C:\Users\mike\envs\xxct3\train\course\urls.py", line 8, in <module>
from .views import (finished_course_view, course_view, index_view,
File "C:\Users\mike\envs\xxct3\train\course\views.py", line 172, in <module>
def course_view(request, pk=None, slug=None):
File "C:\Users\mike\envs\xxct3\lib\site-packages\django\contrib\auth\decorators.py", line 22, in _wrapped_view
if test_func(request.user):
AttributeError: 'function' object has no attribute 'user'If that 'function' is my 'is_login_needed' function I'm inclined to think it obviously has a 'user' attribute.
Here is the contrib.auth.decorators.login_required source (preceded by user_passes_test which it calls) from Django 1.11
My reading of the following is that my own 'is_login_needed' function passed in via @login_required(is_login_needed, login_url='login') as the first positional argument is then passed to the 'user_passes_test' decorator as 'test_func' ...
def user_passes_test(test_func, login_url=None, redirect_field_name=REDIRECT_FIELD_NAME):
"""
Decorator for views that checks that the user passes the given test,
redirecting to the log-in page if necessary. The test should be a callable
that takes the user object and returns True if the user passes.
"""
def decorator(view_func):
@wraps(view_func, assigned=available_attrs(view_func))
def _wrapped_view(request, *args, **kwargs):
if test_func(request.user):
return view_func(request, *args, **kwargs)
path = request.build_absolute_uri()
resolved_login_url = resolve_url(login_url or settings.LOGIN_URL)
# If the login url is the same scheme and net location then just
# use the path as the "next" url.
login_scheme, login_netloc = urlparse(resolved_login_url)[:2]
current_scheme, current_netloc = urlparse(path)[:2]
if ((not login_scheme or login_scheme == current_scheme) and
(not login_netloc or login_netloc == current_netloc)):
path = request.get_full_path()
from django.contrib.auth.views import redirect_to_login
return redirect_to_login(
path, resolved_login_url, redirect_field_name)
return _wrapped_view
return decorator
def login_required(function=None, redirect_field_name=REDIRECT_FIELD_NAME, login_url=None):
"""
Decorator for views that checks that the user is logged in, redirecting
to the log-in page if necessary.
"""
actual_decorator = user_passes_test(
lambda u: u.is_authenticated,
login_url=login_url,
redirect_field_name=redirect_field_name
)
if function:
return actual_decorator(function)
return actual_decoratorCould someone please explain where I'm stuffing up. I reckon I'm confused about which function the AttributeError is complaining.
Many thanks for any help
Mike
No comments:
Post a Comment