简体   繁体   中英

Passing named groups via url via a decorator to a view using RequestFactory

I have a url :

url(r'^p4_users/can_access/(?P<user>[a-zA-Z\.0-9]+)$', 'p4_audit.views.user_can_access')

Which will access a view:

def user_can_access(request, user=None, p4=None):

Via a decorator:

def p4_login_required(f):
    def wrapper(request, *args, **kwargs):
        import re
        if re.search("p4_users/can_access", request.META['PATH_INFO']):
            import pdb; pdb.set_trace()
        if request.user.is_authenticated():
            try:
                p4 = P4.P4()
                p4.port = settings.P4_SERVER
                p4.user = str(request.user.username)
                p4.connect()
                p4.run_login("-s")
                kwargs['p4'] = p4
                return f(request, *args, **kwargs)
            except P4Exception:
                return HttpResponseRedirect("/login")
            except Exception as e:
                return HttpResponse(e)
    return wrapper

Test:

@pytest.mark.user_brett_can_access
def test_brett_can_access(self, p4_conn, create_all, rf):
    request = rf.get("p4_users/can_access/brett.bates")
    request.user = User.objects.get(username="brett.bates")
    response = user_can_access(request)

But when I access this via a RequestFactory pointing to ("/p4_users/can_access/brett.bates"), the p4 variable get's passed fine, but the user variable is None (as the default is). Any ideas as to why?

(Let me know if i can provide more info)

Thanks in advance,

Brett

Your view is expecting user be passed as an keyword argument, but you aren't providing it in the decorator when callin f . You code should be like this:

def p4_login_required(f):
    def wrapper(request, *args, **kwargs):
        import re
        if re.search("p4_users/can_access", request.META['PATH_INFO']):
            import pdb; pdb.set_trace()
        if request.user.is_authenticated():
            try:
                p4 = P4.P4()
                p4.port = settings.P4_SERVER
                p4.user = kwargs['user'] #  You want to check the user param given by the url, right?
                p4.connect()
                p4.run_login("-s")
                kwargs['user'] = p4.user  # Function f (the view) is expecting this
                kwargs['p4'] = p4
                return f(request, *args, **kwargs)
            except P4Exception:
                return HttpResponseRedirect("/login")
            except Exception as e:
                return HttpResponse(e)
    return wrapper

You are directly calling the user_can_access function, and you are not passing the user argument. There is no magic in place that populates the kwargs , and using the request factory, the url conf is completely bypassed. If you want to test the whole thing, from urlconf down to the view, use the test client instead (code here for a method of a Django TestCase, might need adjustment for your setup):

def test_brett_can_access(self):
    resp = self.client.get("/p4_users/can_access/brett.bates")
    # self.assertContains(resp, "...") etc.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM