postgresql 数据库事务问题导致SQLAlchemy ROLLBACK卡住

zysjyyx4  于 2023-11-18  发布在  PostgreSQL
关注(0)|答案(1)|浏览(243)

我有一个Flask应用程序,它使用API,并有一个使用PSQL的多个表的模式。用户应该能够通过搜索栏浏览,以及点击一个流派,以检索图书结果并显示在Bootstrap卡上。用户应该能够收藏/保存一本书,然后被带到他们的个人资料页面,如果注册和登录。我似乎是成功注册,登录,有一个GET到/users/profile,但是我得到了一个ROLLBACK,我被送回登录页面。
这是我的app.py的一部分。我相信我已经导入了所有必要的依赖项。

from flask import Flask, render_template, redirect, flash, session, request, jsonify, url_for
from models import connect_db, db, User, Books
from forms import LoginForm, RegisterForm
from flask_bcrypt import Bcrypt
from flask_login import LoginManager, login_required

app = Flask(__name__, template_folder="templates", static_folder="static")

app.app_context().push()

from flask_login import current_user
from flask_login import login_user, logout_user

bcrypt = Bcrypt()
login_manager = LoginManager()
login_manager.init_app(app)

app.config["SQLALCHEMY_DATABASE_URI"] = "postgresql:///my_books"
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False
app.config["SQLALCHEMY_ECHO"] = True
app.config["SECRET_KEY"] = ""
app.config['TESTING'] = True

import requests

API_KEY = ""
migrate = Migrate(app, db)

connect_db(app)

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

字符串
这是login_manager.user_loader,我相信我正确导入了user_id。

@login_manager.user_loader
def user_loader(user_id):
    if user_id.isdigit():
        user = User.query.get(int(user_id))
        return user
    return None**


这是我的登录GET路由,显示了登录表单。

@app.route("/users/login", methods=["GET"])
def login_form():
    """Displays the login form."""
    form = LoginForm()
    return render_template('users/login.html', form=form)


这是我的登录路线,应该带我到profile.html页面一旦登录。

from flask import current_app

@app.route("/users/login", methods=["POST"])
def login():
    """Displays login form. Logs in the current user by processing the form"""
    form = LoginForm()
    if form.validate_on_submit():
        user = User.query.filter_by(username=form.username.data).first()
        print("Username from form:", form.username.data)
        print("User from the database:", user)
        
        if user:
            if login_user(user):
                print("Login successful")
                flash(f"Hello, {user.username}!", "success")
                db.session.commit()  # Commit the transaction to the database
                return redirect(url_for('profile'))
            else:
                print("Login failed")
                flash("Failed to log in the user.", "danger")
        else:
            print("User not found")
            flash("User not found.", 'danger')
    else:
        flash("Invalid credentials.", 'danger')

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


我做了许多flash和print语句,我想是因为回滚的原因,这些语句没有出现。

@app.route("/users/logout", methods=["GET"])
def logout():
    """Logout the current user."""
    logout_user()  # Use Flask-Login logout_user function
    return redirect(url_for('home_page'))

@app.route('/users/register', methods=["GET", "POST"])
def handle_registration():
    """Creates a new user and adds user to the DB. Makes sure username & email are unique."""
    form = RegisterForm()

    if form.validate_on_submit():
        # Check if a user with the same username or email already exists
        existing_user = User.query.filter((User.username == form.username.data) | (User.email == form.email.data)).first()

        if existing_user:
            flash("Username or email already taken", 'danger')
            return render_template('users/register.html', form=form)

        user = User.signup(
            first_name=form.first_name.data,
            last_name=form.last_name.data,
            username=form.username.data,
            password=form.password.data,
            email=form.email.data,
        )
        db.session.commit()

        flash("Registration successful! Please log in.", 'success')
        return redirect(url_for('login_form'))

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

from flask_login import current_user

@app.route('/users/profile', methods=["GET"])
def profile():
    if current_user.is_anonymous:
        flash("You need to log in to see your profile.", 'warning')
        return redirect(url_for('login'))
    print("Profile route accessed")

    # Retrieve the current user's favorite books
    favorite_books = current_user.saved_books
    
    return render_template('users/profile.html', favorite_books=favorite_books)


我的Flask应用程序加载,我可以浏览,搜索和注册假帐户,所以WTForms的注册页面可以正常工作。当我进入登录页面并输入我的用户名和密码时,我可以看到HTML中的登录标记已经切换到注销标记,所以这似乎也可以正常工作。我还检查了我的模式中的所有数据库都显示在PSQL中。
这是我的models.py:

from flask_sqlalchemy import SQLAlchemy
from datetime import datetime
from flask_login import UserMixin

db = SQLAlchemy()

saved_books_association = db.Table(
    'saved_books_association',
    db.Column('user_id', db.Integer, db.ForeignKey('users.id')),
    db.Column('book_id', db.Integer, db.ForeignKey('books.id'))
)


这是User类继续models.py。我试图跟随沿着与真实的Python网站。

class User(db.Model, UserMixin):

    __tablename__ = "users"

    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(20), nullable=False, unique=True)
    first_name = db.Column(db.String(20), nullable=False)
    last_name = db.Column(db.String(20), nullable=False)
    email = db.Column(db.String(50), nullable=False)
    password = db.Column(db.String(100), nullable=False)
    saved_books = db.relationship('Books', secondary=saved_books_association, backref=db.backref('users', lazy='dynamic'))
    

    def __init__(self, first_name, last_name, username, email, password):
        self.first_name = first_name
        self.last_name = last_name
        self.username = username
        self.email = email
        self.password = bcrypt.generate_password_hash(password).decode('utf-8')

    def check_password(self, password):
        return bcrypt.check_password_hash(self.password, password)
    
    @classmethod
    def signup(cls, first_name, last_name, username, password, email):
        """Sign up a new user and return the user object."""
        user = cls(first_name=first_name, last_name=last_name, username=username, password=password, email=email)
        db.session.add(user)
        return user

    def is_active(self):
        """True, as all users are active."""
        return True

    def get_id(self):
        """Return the user's ID as a string to satisfy Flask-Login's requirements."""
        return str(self.id)

    def is_anonymous(self):
        """Return True if the user is anonymous, or False if authenticated."""
        return not self.is_authenticated()**


我还有其他没有包含的DB模型。这是运行Flask应用程序时终端中的消息:

127.0.0.1 - - [01/Nov/2023 19:30:09] "POST /users/login HTTP/1.1" 302 -
2023-11-01 19:30:09,361 INFO sqlalchemy.engine.Engine BEGIN (implicit)
2023-11-01 19:30:09,361 INFO sqlalchemy.engine.Engine SELECT users.id AS users_id, users.username AS users_username, users.first_name AS users_first_name, users.last_name AS users_last_name, users.email AS users_email, users.password AS users_password 
FROM users 
WHERE users.id = %(pk_1)s
2023-11-01 19:30:09,361 INFO sqlalchemy.engine.Engine [cached since 23.39s ago] {'pk_1': 1}
2023-11-01 19:30:09,362 INFO sqlalchemy.engine.Engine ROLLBACK
127.0.0.1 - - [01/Nov/2023 19:30:09] "GET /users/profile HTTP/1.1" 302 -
2023-11-01 19:30:09,367 INFO sqlalchemy.engine.Engine BEGIN (implicit)
2023-11-01 19:30:09,367 INFO sqlalchemy.engine.Engine SELECT users.id AS users_id, users.username AS users_username, users.first_name AS users_first_name, users.last_name AS users_last_name, users.email AS users_email, users.password AS users_password 
FROM users 
WHERE users.id = %(pk_1)s
2023-11-01 19:30:09,367 INFO sqlalchemy.engine.Engine [cached since 23.4s ago] {'pk_1': 1}
2023-11-01 19:30:09,369 INFO sqlalchemy.engine.Engine ROLLBACK
127.0.0.1 - - [01/Nov/2023 19:30:09] "GET /users/login HTTP/1.1" 200 -


我已经尝试删除我的数据库并重新创建它,更改为使用UserMixin,并重新修改了我的User类模型无数次,我仍然停留在回滚上。任何建议都将是一个很大的帮助。

qnakjoqk

qnakjoqk1#

每次使用会话时,都会自动启动一个事务,然后它将被回滚。所以这可能是不相关的。
if current_user.is_anonymous:应该是像if current_user.is_anonymous():这样的函数调用吗?

相关问题