如何使用自定义装饰器测试视图与django中的用户有关?

时间:2013-07-18 04:54:23

标签: django decorator django-testing python-decorators

我的观点如下:

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

active_required客户装饰器如下所示:

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

我的测试看起来像这样:

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)

我收到以下错误:

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

如果在测试中创建的数据库不包含此活动用户,我该如何添加它们?或者我是否因为其他原因而收到此错误?

1 个答案:

答案 0 :(得分:0)

好好看Django login_reguired source login_required作为第一个参数function,这个参数将被装饰。

所以我认为这段代码应该有效:

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

如果此代码不起作用(尚未测试),您可以使用user_passes_test装饰器:

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

这个位于上面的链接上,第一个参数是function,而function必须接受参数为user的参数

这样做我确信你的代码必须有效:

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'