Why are instances from my code not being added to my database?

Viewed 50

I'm building a simple app with Python and Flask that allows a user to sign up, login, browse items, save favorites, etc. In several places in my code it seems that when I create an instance of something, it's not getting added to my models and so I can't do anything with it. For example, when a user who has previously signed up tries to login, nothing happens. I've made about a dozen dummy accounts, and what's really odd is that one works and the rest don't. I went into psql in Terminal to look at the Users table, and sure enough it's just the one account that got added to it. If I login with that account everything goes perfectly, and with all the other accounts nothing happens when I click login.

Later on in the code, I try to create instances for parks in one of my routes, and when I try to go to the individual page for a park I get a 404 because none of the parks are being added to the parks table. I can show that too, but the syntax I'm using is the same.

@app.route('/signup', methods=["GET", "POST"])
def signup():

    form = NewUserForm()
    if form.validate_on_submit():
        user = User.signup(
            username=form.username.data,
            password=form.password.data,
            email=form.email.data,
            )
        
        db.session.commit()

        do_login(user)

        return redirect("/parks")

    else:
        return render_template('signup.html', form=form)


@app.route('/login', methods=["GET", "POST"])
def login():
    """Handle user login."""

    form = LoginForm()
    if form.validate_on_submit():
        user = User.authenticate(form.username.data,
                                 form.password.data)

        if user:
            do_login(user)
            flash(f"Hello, {user.username}!")
            return redirect("/parks")

    flash("Username and/or password are incorrect", 'danger')

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

Here's the model for user if that helps:

class User(db.Model):
    """User in the system."""

    __tablename__ = 'users'

    id = db.Column(
        db.Integer,
        primary_key=True,
    )

    email = db.Column(
        db.Text,
        nullable=False,
        unique=True,
    )

    username = db.Column(
        db.Text,
        nullable=False,
        unique=True,
    )

    password = db.Column(
        db.Text,
        nullable=False,
    )


    @classmethod
    def signup(cls, username, email, password):

        hashed_pwd = bcrypt.generate_password_hash(password).decode('UTF-8')

        user = User(
            username=username,
            email=email,
            password=hashed_pwd,
        )

        db.session.add(user)
        return user

    @classmethod
    def authenticate(cls, username, password):

        user = cls.query.filter_by(username=username).first()

        if user:
            is_auth = bcrypt.check_password_hash(user.password, password)
            if is_auth:
                return user

        return False
1 Answers

It seems you're using SQLAlchemy? If so, it isn't enough to Session.add() an object to write it to the database; the actual database INSERT happens when you execute a Session.flush(), which performs all changes that got queued.

@classmethod
def signup(cls, username, email, password):

    hashed_pwd = bcrypt.generate_password_hash(password).decode('UTF-8')

    user = User(
        username=username,
        email=email,
        password=hashed_pwd,
    )

    db.session.add(user)
    db.session.flush()  # add this
    return user
Related