سؤال

I have a view that looks like this:

@login_required 
@active_required()
def myView(request):
      print 'in my view'

The active_required customer decorator looks like this:

def active_required():
    def decorator(func):
        def inner_decorator(request, *args, **kwargs):
            my_user = request.user
            if my_user.active:
                return func(request, *args, **kwargs)
            else:
                    return HttpResponseRedirect(reverse('activate'))

        return wraps(func)(inner_decorator)

    return decorator

My test looks like this:

def test_my_view(self):
    self.client.login(username='user', password='11111111')
    response = self.client.post(reverse('my-view'), data, follow=True)
    self.assertEqual(response.status_code, 200)

I get the following error:

 @active_required
 TypeError: active_required() takes no arguments (1 given)

If the database that is created in the test doesn't contain this user that is active, how do I add them? Or am I receiving this error for another reason?

هل كانت مفيدة؟

المحلول

Well looking at the Django login_reguired source login_required takes as first parameter the function that this one will be decorated.

So I think this code should works:

def active_required(func):
        @wraps(func)
        def inner_decorator(request, *args, **kwargs):
            my_user = request.user
            if my_user.active:
                return func(request, *args, **kwargs)
            else:
                    return HttpResponseRedirect(reverse('activate'))

        return inner_decorator

    return active_required

If this code does not work (Has not been tested yet) you can use user_passes_test decorator :

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()
            # urlparse chokes on lazy objects in Python 3, force to str
            resolved_login_url = force_str(
                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

This one is on the link above and the first parameter this one takes it's a function and that function must accept an parameter that parameter is the user

So doing this I'm sure your code must works:

from django.contrib.auth.decorators import user_passes_test, login_required
@login_required 
@user_passes_test(lambda user: user.is_active())
def myView(request):
      print 'in my view'
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top