blueblank
blueblank

Reputation: 4894

AttributeError: 'RequestContext' object has no attribute 'user'

I'm getting this error, and I'd like any sort of input because it is a brick wall right now.

I have an application, that is using flask-security, which imports current_user through flask-login. Any integration issues are in the past and have been for some time.

I had a need to filter the request for some specific information, which I place on g. I had a blueprint which worked, and any integration issues are in the past.

Yesterday, I extracted this request filtering blueprint functions to a general extension, which basically filters info to g, and becomes easier to configure, so it is more or less ready and tested to go. This extension replaces this blueprint to make a cross application request filter

I put this back into my application, ONLY now I'm getting this, and as stated it is opaque: I don't know where or why user is not in RequestContext

Traceback (most recent call last):
  File "/home/zv/.virtualenvs/j/lib/python2.7/site-packages/flask/app.py", line 1701, in __call__
    return self.wsgi_app(environ, start_response)
  File "/home/zv/.virtualenvs/j/lib/python2.7/site-packages/flask/app.py", line 1689, in wsgi_app
    response = self.make_response(self.handle_exception(e))
  File "/home/zv/.virtualenvs/j/lib/python2.7/site-packages/flask/app.py", line 1687, in wsgi_app
    response = self.full_dispatch_request()
  File "/home/zv/.virtualenvs/j/lib/python2.7/site-packages/flask/app.py", line 1360, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File "/home/zv/.virtualenvs/j/lib/python2.7/site-packages/flask/app.py", line 1356, in full_dispatch_request
    rv = self.preprocess_request()
  File "/home/zv/.virtualenvs/j/lib/python2.7/site-packages/flask/app.py", line 1539, in preprocess_request
    rv = func()
  File "/home/zv/.virtualenvs/j/lib/python2.7/site-packages/Flask_Flarf-0.0.1-py2.7.egg/flask_flarf/flarf.py", line 48, in preprocess_request
    preprocess_func(r)
  File "/home/zv/.virtualenvs/j/lib/python2.7/site-packages/Project_Producer-0.0.1-py2.7.egg/project_producer/config/configs/request_filters_config.py", line 10, in preprocess_with_user
    g.preprocessed = current_app.extensions['flarf'].preprocess_cls(request)
  File "/home/zv/.virtualenvs/j/lib/python2.7/site-packages/Project_Producer-0.0.1-py2.7.egg/project_producer/config/configs/request_filters_config.py", line 17, in __init__
    self.aid = self.determine_account(request)
  File "/home/zv/.virtualenvs/j/lib/python2.7/site-packages/Project_Producer-0.0.1-py2.7.egg/project_producer/config/configs/request_filters_config.py", line 51, in determine_account
    current_user.account.identifier])
  File "/home/zv/.virtualenvs/j/lib/python2.7/site-packages/werkzeug/local.py", line 336, in __getattr__
    return getattr(self._get_current_object(), name)
  File "/home/zv/.virtualenvs/j/lib/python2.7/site-packages/werkzeug/local.py", line 295, in _get_current_object
    return self.__local()
  File "/home/zv/.virtualenvs/j/lib/python2.7/site-packages/flask_login.py", line 403, in <lambda>
    current_user = LocalProxy(lambda: _request_ctx_stack.top.user)
AttributeError: 'RequestContext' object has no attribute 'user'

theories:

1) this function:

def preprocess_request(preprocess_func=self.preprocess_func):
        r = _request_ctx_stack.top.request
        request_endpoint = str(r.url_rule.endpoint).rsplit('.')[-1]
        if request_endpoint not in _flarf.preprocess_skip:
            preprocess_func(r)

so what is happpening above in the trace is that the preprocess_request runs calls an app local defined preprocess_func that itself creates an app local defined class instance to attach to g, this locally defined class instance uses 'current_user'...and that is where it errors.

gets run around, before, or something that using _request_ctx_stack is not yet in touch with user or removes user. multiply popping or touching _request_ctx_stack.top.request is maybe 'not good'

2) order of operation, preprocess_request is running before flask-security is adding a user

3) no clue, a bit lost atm

Any suggestions?

EDIT:

The issue is most likely method resolution as current_app.before_request_funcs return:

{None: [<function flarf_filter_request at 0x1a781b8>, <bound method LoginManager._load_user of <flask_login.LoginManager object at 0x1a79990>>, <bound method Principal._on_before_request of <flask_principal.Principal object at 0x1a80290>>]}

so main takeaway is that I'm doing it wrong, where if I need to get before_request info, getting that info within the before_request time that flask runs those function is not optimal as there is currently no ordering of before_request functions.

Options?

  1. Add an option to order before_request functions to flask, possibly as simple as a precedence keyword and call to sorted or an ordered dict

  2. Change tactics with what I'm doing, e.g. change this from a before_request to a decorator. But, that would require a per view notation and the whole point of creating the blueprint and extension was to skip having to gather certain information on a per view basis. Upside would be multiple filters which was planned.

  3. A useful, premade solution: Flask-Classy


Upvotes: 2

Views: 4929

Answers (1)

radtek
radtek

Reputation: 36270

Hey I ran into this as well but with Django, exact same error. So I thought this may be similar. The RequestContext isn't a request but it contains it. Its a special class in django and when its created by your view it actually contains the request along with all your other context variables that you pass from the view to the template.

Here is how it is created:

c = RequestContext(request, {
    'foo': 'bar',
})

More on that here. And in Flask docs.

Long story short, the RequestContext is a dict that contains the request inside the 'request' key. So you can access it as such:

request = context['request']
user = request.user

In your template you access request as you would normally, request.user should work. Hope this helps, I have a feeling that this may be similar in Flask and in Django. If this doesn't help you can print out your context and see what data it contains. Thats how I figured out my problem.

Cheers

Upvotes: 3

Related Questions