首页 > 解决方案 > 具有多个用户类的 Flask-Login

问题描述

所以在我的烧瓶项目中,我使用了 Flask-Login 来实现登录/注册系统。然而,这是我的用户表。我还有一个“助推器”表,它具有几乎相同的属性,但更多。例如,助推器将登录到网站的不同部分。我有它的路线分开。所以我的路线是/login、/register 和/booster_login 和/booster_register。我尝试在 booster_login 下的登录方法上使用 login_user 方法,但是当我提交 booster_login 表单时,我得到一个对象没有 is_active 属性。我不能只使用角色,因为助推器将拥有比用户更多的属性。

我的models.py在这里

from flask_login import UserMixin
from flask_sqlalchemy import SQLAlchemy
from flask_admin import Admin    
from flask_socketio import SocketIO, join_room
import datetime

db = SQLAlchemy()
socketio = SocketIO()

class User(UserMixin, db.Model):
    __tablename__ = 'users'
    id = db.Column(db.Integer, primary_key=True)  
    username = db.Column(db.String(20), unique=True)
    email = db.Column(db.String(50), unique=True)
    password = db.Column(db.String(80))
    role = db.Column(db.String(80))

class Booster(db.Model):

    id = db.Column(db.Integer, primary_key=True)
    booster_name = db.Column(db.String(20), nullable=False)
    password = db.Column(db.String(20), nullable=False)
    email = db.Column(db.String(50), nullable=False)
    join_date = db.Column(db.DateTime(timezone=True))
    current_order = db.Column(db.Integer, db.ForeignKey('orders.id'))
    current_balance = db.Column(db.Float)

    def __init__(self, booster_name, email, password, join_date):
        self.booster_name = booster_name
        self.password = password
        self.email = email
        self.join_date = join_date

https://github.com/bshel​​ton/flask-boost/blob/master/views.py

from flask import Flask, render_template, redirect, url_for, Blueprint, request

from flask_login import LoginManager, UserMixin, login_user, login_required, logout_user, current_user   
from flask_sqlalchemy import SQLAlchemy, functools
from sqlalchemy import func
from flask_wtf import FlaskForm
#from wtforms import StringField, PasswordField, BooleanField
from passlib.hash import sha256_crypt
from .boostforms import LoginForm, RegisterForm, SoloOrderForm

from .models import User, db, socketio, ChatLog, Orders, join_room, Booster

import datetime

mainbp = Blueprint('mainbp', __name__, template_folder='templates', static_folder='static') 

users = {}

@mainbp.route('/')

def index():   
    return render_template('index.html')

@mainbp.route('/login', methods=['GET', 'POST'])  
def login():  
    form = LoginForm() 
    if form.validate_on_submit():

        submitted_username = form.username.data

        submitted_username = str(submitted_username)

        submitted_username = submitted_username.lower() 

        user = User.query.filter(func.lower(User.username)==submitted_username).first()

        print (user)   
        if user:

            if user.username.lower() == submitted_username.lower():

                if sha256_crypt.verify(form.password.data, user.password) and user.role == "Admin":

                    login_user(user, remember=form.remember.data)

                    return redirect(request.args.get('next') or url_for('.admindashboard'))

                elif sha256_crypt.verify(form.password.data, user.password) and user.role == "Client":

                    login_user(user, remember=form.remember.data)

                    return redirect(request.args.get('next') or url_for('.userdashboard'))

                else: 
                     return '<h1> You\'re stupid </h1>' 
            else:  
                return '<h1> Invalid Login </h1>'  
        else:
            return '<h1> Invalid Login </h1>'

    return render_template('login.html', form=form)

@mainbp.route('/boosterlogin', methods=["GET", "POST"])   
def boosterlogin():
    form = LoginForm()

    if form.validate_on_submit():

        submitted_username = form.username.data

        submitted_username = str(submitted_username)

        submitted_username = submitted_username.lower()

        booster = Booster.query.filter(func.lower(Booster.booster_name)==submitted_username).first()

        print (booster.booster_name)

        if booster:

            print (booster.password)

            print (form.password.data)

            if booster.booster_name.lower() == submitted_username.lower():

                if sha256_crypt.verify(form.password.data, booster.password):

                    login_user(booster, remember=form.remember.data)

                    return redirect(request.args.get('next') or url_for('.index'))

                else:

                     return '<h1> Wrong Password </h1>'

            else:
                return '<h1> Invalid Login </h1>'

        else:

            return '<h1> Invalid Login </h1>'



    return render_template('boosterlogin.html', form=form)


@mainbp.route('/logout')
@login_required 
def logout():
    logout_user()

    return redirect(url_for('.index'))
@mainbp.route('/register', methods=['GET', 'POST'])
def register():

    form = RegisterForm()

    if form.validate_on_submit():

        hash_password = sha256_crypt.hash(form.password.data)

        new_user = User(username=form.username.data, email=form.email.data, password=hash_password)

        db.session.add(new_user)

        db.session.commit()

        return redirect(url_for('.login'))

    return render_template('register.html', form=form)

@mainbp.route('/booster_register', methods=['GET', 'POST'])
def booster_register():

    form = RegisterForm()

    if form.validate_on_submit():

        booster_name = form.username.data

        hash_password = sha256_crypt.hash(form.password.data)

        email = form.email.data

        join_date = datetime.datetime.now()

        print ("booster_name: " + booster_name + " password: " + hash_password + " email: " + email)

        new_booster = Booster(booster_name=booster_name, email=email, password=hash_password, join_date=datetime.datetime.now())

        db.session.add(new_booster)

        db.session.commit()

        return redirect(url_for('.boosterlogin'))

    return render_template('booster_register.html', form=form)

标签: pythonflaskflask-sqlalchemy

解决方案


当您使用烧瓶登录login()方法时,它将期望一个UserMixin实现这些缺失属性的对象。在您的代码中,您仅在 User 模型中实现 UserMixin。尝试让 Booster 从您的User类继承,如下所示。

class Booster(User):

    id = db.Column(db.Integer, primary_key=True)
    booster_name = db.Column(db.String(20), nullable=False)
    password = db.Column(db.String(20), nullable=False)
    email = db.Column(db.String(50), nullable=False)
    join_date = db.Column(db.DateTime(timezone=True))
    current_order = db.Column(db.Integer, db.ForeignKey('orders.id'))
    current_balance = db.Column(db.Float)

    def __init__(self, booster_name, email, password, join_date):
        self.booster_name = booster_name
        self.password = password
        self.email = email
        self.join_date = join_date

推荐阅读