Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Flask-Login:Where user_loader callback should be defined?

I am new to python coding but straightaway started experimenting with flask. I am having trouble with flask-login extension Here I am making a simple application which is a blog. This blog is going to be used by one person only.

I cannot understand why the user_loader decorator not working which is defined in models.py. I get exception the application NoneType object is not callable. My app structure is like this

.
|-- app
|   |-- admin
|   |   |-- __init__.py
|   |   |-- static
|   |   |-- templates
|   |   `-- views.py
|   |-- config.py
|   |-- __init__.py
|   |-- main
|   |   |-- __init__.py
|   |   |-- static
|   |   |-- templates
|   |   `-- views.py
|   `-- models.py
`-- launch.py

app.init

from flask import Flask
from main import main
from admin import admin
from flask.ext.script import Manager
from .config import config
from flask_debugtoolbar import DebugToolbarExtension
from flask.ext.sqlalchemy import SQLAlchemy
from sqlalchemy import Column
from flask_bootstrap import Bootstrap
from flask.ext.moment import Moment
from flask.ext.login import LoginManager


app_myblog=Flask(__name__)
app_myblog.debug=True
app_myblog.config.from_object(config)
app_myblog.register_blueprint(main)
app_myblog.register_blueprint(admin,url_prefix="/admin"
toolbar=DebugToolbarExtension(app_myblog)
manager=Manager(app_myblog)
db=SQLAlchemy(app_myblog)
Bootstrap(app_myblog)
moment=Moment(app_myblog)

login_manager=LoginManager()
login_manager.init_app(app_myblog)
login_manager.session_protection='strong'
login_manager.login_view='admin.login'

In app.models I have defined User class which does not load users from database. In fact it simply loads user from configuration. In same file I have also defined user_loader callback

class User(UserMixin):
    def __init__(self):
        self.id='1'
        self.name=app_myblog.config['USERNAME']
        self.password=app_myblog.config['PASSWORD']

    def get_id(self):
        return unicode(id)

@login_manager.user_loader
def load_user(userid):
    u=User()
    if u.get_id()==userid:
        return u
    else:
        return None

admin.init

from flask import Blueprint

admin=Blueprint('admin',__name__,template_folder='templates',static_folder='static')
from . import views

admin.views

from flask import render_template,request,redirect,url_for
from . import admin
from flask.ext.login import login_required,login_user
from flask_wtf.form import Form
from wtforms import StringField,PasswordField,SubmitField
from ..models import User



class LoginForm(Form):
    username=StringField('Username')
    password=PasswordField('Password')
    submit=SubmitField('Login')


@admin.route('/')
@login_required
def index():
    return render_template('admin_home.html')


@admin.route('/login',methods=['GET','POST'])
def login():
    form=LoginForm()
    if form.validate_on_submit():
        login_user(User())
        nextx = request.args.get('next')
        return redirect(nextx or url_for('admin.index'))
    return render_template('admin_login.html',form=form)

Whenever i run the routes which have login_required i get the error TypeError: 'NoneType' object is not callable. Here is the traceback.

Traceback (most recent call last):
  File "/home/shivam/Workspaces/PythonWorkSpace/MyBlog/venv/lib/python2.7/site-packages/flask/app.py", line 1836, in __call__
    return self.wsgi_app(environ, start_response)
  File "/home/shivam/Workspaces/PythonWorkSpace/MyBlog/venv/lib/python2.7/site-packages/flask/app.py", line 1820, in wsgi_app
    response = self.make_response(self.handle_exception(e))
  File "/home/shivam/Workspaces/PythonWorkSpace/MyBlog/venv/lib/python2.7/site-packages/flask/app.py", line 1403, in handle_exception
    reraise(exc_type, exc_value, tb)
  File "/home/shivam/Workspaces/PythonWorkSpace/MyBlog/venv/lib/python2.7/site-packages/flask/app.py", line 1817, in wsgi_app
    response = self.full_dispatch_request()
  File "/home/shivam/Workspaces/PythonWorkSpace/MyBlog/venv/lib/python2.7/site-packages/flask/app.py", line 1477, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File "/home/shivam/Workspaces/PythonWorkSpace/MyBlog/venv/lib/python2.7/site-packages/flask/app.py", line 1381, in handle_user_exception
    reraise(exc_type, exc_value, tb)
  File "/home/shivam/Workspaces/PythonWorkSpace/MyBlog/venv/lib/python2.7/site-packages/flask/app.py", line 1475, in full_dispatch_request
    rv = self.dispatch_request()
  File "/home/shivam/Workspaces/PythonWorkSpace/MyBlog/venv/lib/python2.7/site-packages/flask_debugtoolbar/__init__.py", line 125, in dispatch_request
    return view_func(**req.view_args)
  File "/home/shivam/Workspaces/PythonWorkSpace/MyBlog/venv/lib/python2.7/site-packages/flask_login.py", line 756, in decorated_view
    elif not current_user.is_authenticated():
  File "/home/shivam/Workspaces/PythonWorkSpace/MyBlog/venv/lib/python2.7/site-packages/werkzeug/local.py", line 338, in __getattr__
    return getattr(self._get_current_object(), name)
  File "/home/shivam/Workspaces/PythonWorkSpace/MyBlog/venv/lib/python2.7/site-packages/werkzeug/local.py", line 297, in _get_current_object
    return self.__local()
  File "/home/shivam/Workspaces/PythonWorkSpace/MyBlog/venv/lib/python2.7/site-packages/flask_login.py", line 46, in <lambda>
    current_user = LocalProxy(lambda: _get_user())
  File "/home/shivam/Workspaces/PythonWorkSpace/MyBlog/venv/lib/python2.7/site-packages/flask_login.py", line 794, in _get_user
    current_app.login_manager._load_user()
  File "/home/shivam/Workspaces/PythonWorkSpace/MyBlog/venv/lib/python2.7/site-packages/flask_login.py", line 363, in _load_user
    return self.reload_user()
  File "/home/shivam/Workspaces/PythonWorkSpace/MyBlog/venv/lib/python2.7/site-packages/flask_login.py", line 325, in reload_user
    user = self.user_callback(user_id)
TypeError: 'NoneType' object is not callable
like image 537
user274823 Avatar asked Jun 24 '15 16:06

user274823


People also ask

Which of the following can be used to login a user in Flask?

Flask-login also requires you to define a “user_loader” function which, given a user ID, returns the associated user object. The @login_manager. user_loader piece tells Flask-login how to load users given an id. I put this function in the file with all my routes defined, as that's where it's used.

Does Flask-Login use session?

By default, Flask-Login uses sessions for authentication. This means you must set the secret key on your application, otherwise Flask will give you an error message telling you to do so. See the Flask documentation on sessions to see how to set a secret key.


2 Answers

Edit: I created a minimal example of your code and the the difference was that I removed the get_id(self) function (+ some extra libraries that isn't needed), beacuse it's part of the UserMixin class that you inherit.

Are you sure your form is getting validated? Can you describe how you test this step by step? I mean, "go to login.html" -> "enter credentials" -> etc

Make sure which call is causing the crash, is it the redirect inside your login function?

like image 159
Zyber Avatar answered Oct 26 '22 03:10

Zyber


You should define the method in the same place you instantiate the login manager.

ala

login = LoginManager
@login.user_loader
def load_user(id/email):
    #your logic here

Or import your loginmanager instance from your module and define in your views.

like image 28
Callam Delaney Avatar answered Oct 26 '22 05:10

Callam Delaney