1

I'm trying to add Flask-Login to my Flask-Python app but I'm having this error and I don't know why. I guess thats my user.loader that isnt correct but the idea is to load the user based on the ID or email.

What am I doing wrong?

full error:

DataError: (psycopg2.DataError) invalid input syntax for integer:
"[email protected]" LINE 3: WHERE users.uid = '[email protected]'

app.py

from flask import Flask, render_template, request, session, redirect, url_for
from models import db, User
from forms import SignupForm, LoginForm
from flask_login import LoginManager, UserMixin, \
                                login_required, login_user, logout_user

app = Flask(__name__)

app.config['SQLALCHEMY_DATABASE_URI'] = 'postgresql://localhost/polex'
db.init_app(app)

login_manager = LoginManager()
login_manager.init_app(app)
login_manager.login_view = "login"

app.secret_key = "development-key"


@login_manager.user_loader
def user_loader(uid):
    """Given *user_id*, return the associated User object.

    :param unicode user_id: user_id (email) user to retrieve
    """
    return User.query.get(uid)


@app.route("/")
def index():
  return render_template("index.html")

@app.route("/about")
def about():
  return render_template("about.html")

@app.route("/signup", methods=["GET", "POST"])
def signup():
  if 'email' in session:
    return redirect(url_for('home'))

  form = SignupForm()

  if request.method == "POST":
    if form.validate() == False:
      return render_template('signup.html', form=form)
    else:
      newuser = User(form.first_name.data, form.last_name.data, form.email.data, form.password.data)
      db.session.add(newuser)
      db.session.commit()

      session['email'] = newuser.email
      return redirect(url_for('home'))

  elif request.method == "GET":
    return render_template('signup.html', form=form)

@app.route("/login", methods=["GET", "POST"])
def login():
  print db
  
  form = LoginForm()

  if request.method == "POST":
    if form.validate() == False:
      return render_template("login.html", form=form)
    else:
      email = form.email.data 
      password = form.password.data 

      user = User.query.filter_by(email=email).first()
      if user is not None and user.check_password(password):
        login_user(user, remember=True) 
        return redirect(url_for('home'))
      else:
        return redirect(url_for('login'))

  elif request.method == 'GET':
    return render_template('login.html', form=form)

@app.route("/logout")
def logout():
  session.pop('email', None)
  return redirect(url_for('index'))

@app.route("/home", methods=["GET", "POST"])

def home():
  

  return render_template("home.html")

if __name__ == "__main__":
  app.run(debug=True)

models.py

from flask_sqlalchemy import SQLAlchemy
from werkzeug import generate_password_hash, check_password_hash
from flask_login import UserMixin

db = SQLAlchemy()

class User(db.Model):
  __tablename__ = 'users'
  uid = db.Column(db.Integer, primary_key = True)
  firstname = db.Column(db.String(100))
  lastname = db.Column(db.String(100))
  email = db.Column(db.String(120), unique=True)
  pwdhash = db.Column(db.String(54))

  #-----login requirements-----
  def is_active(self):
    #all users are active
    return True 

  def get_id(self):
        # returns the user e-mail. not sure who calls this
    return self.email

  def is_authenticated(self):
    return self.authenticated

  def is_anonymous(self):
        # False as we do not support annonymity
    return False

  def __init__(self, firstname, lastname, email, password):
    self.firstname = firstname.title()
    self.lastname = lastname.title()
    self.email = email.lower()
    self.set_password(password)
     
  def set_password(self, password):
    self.pwdhash = generate_password_hash(password)

  def check_password(self, password):
    return check_password_hash(self.pwdhash, password)

1 Answer 1

1

You're using User.query.get(uid) where you need to use filter or filter_by:

@login_manager.user_loader
def user_loader(user_email):
    """Given *user_id*, return the associated User object.

    :param unicode user_id: user_id (email) user to retrieve
    """
    return User.query.filter_by(email=user_email).first()

get() takes a Primary Key (which would be user id in this case) and returns it, filter is what you need here if you're trying to limit on a column value.

Sign up to request clarification or add additional context in comments.

5 Comments

Thanks for your comment. I tried that but I got TypeError: Boolean value of this clause is not defined
@Perseverance care to try the above modification, with filter_by?
Well, It actually changed the error to AttributeError: 'BaseQuery' object has no attribute 'is_authenticated'and as you can see I have that on my model. Is that user_email, correct? Because I'm not referring to the User on my model.py. How do it parses the email like that? Sorry for bothering and thank you!
@Perseverance ah, ok that's because it returns a query not a user. I've edited my answer again for you. Note the first() method being called on the result.
Oh, that's how I have on my login function. It's working now. But I can visit home page even tho I'm not logged it. This is bad

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.