SQLALchemy, Flask, Python, code adds model object only once to database (PostgreSQL)

Question:

My database looks like this:

CREATE TYPE APP_ROLE AS ENUM ('admin', 'user');

CREATE TABLE IF NOT EXISTS users (
  user_id SERIAL PRIMARY KEY,
  login VARCHAR ( 50 ) UNIQUE NOT NULL,
  password_hash TEXT NOT NULL,
  role APP_ROLE NOT NULL
);

I wrote a simple Flask/SQLAlchemy/Python code to test inserting to db. However, it seems that my object is added only once, because no matter how many time I run the script (python3 testdb.py) it shows that there’s only one user in db. What Im doing wrong?

#!/usr/bin/env python3
import os
from flask import Flask, render_template, request, url_for, redirect
from flask_sqlalchemy import SQLAlchemy
from sqlalchemy import inspect
from sqlalchemy import create_engine
from sqlalchemy import Enum
from werkzeug.security import generate_password_hash

basedir = os.path.abspath(os.path.dirname(__file__))

class Config(object):
    DEBUG = False
    TESTING = False
    CSRF_ENABLED = True
    SQLALCHEMY_TRACK_MODIFICATIONS = False
    SQLALCHEMY_DATABASE_URI = "postgresql://brian:[email protected]:5432/example_db"


app = Flask(__name__)
app.config.from_object(Config)
db = SQLAlchemy(app)

class Users(db.Model):

    __tablename__ = 'users'

    user_id = db.Column(db.Integer, primary_key=True)
    login = db.Column(db.String(50), unique=True)
    password_hash = db.Column(db.String(128))
    role = db.Column(Enum("admin", "user", name="app_role", create_type=False))

    def __init__(self, login, password_hash, role):
        self.login = login
        self.password_hash = password_hash
        self.role = role

    @property
    def password(self):
        raise AttributeError('Password is not a readable attribute')

    @password.setter
    def password(self, password):
        self.password_hash = generate_password_hash(password)

    def to_json(self):
        pass

    def is_administrator(self):
        pass

if __name__ == '__main__':

    u1 = Users('brian', '2345643245', 'admin')
    db.create_all()
    db.session.add(u1)
    db.session.add(u1)
    db.session.add(u1)
    db.session.flush()
    
    users1 = Users.query.all()
    for user in users1:
        print(user.login, user.password_hash, user.role)
Asked By: Brian Brown

||

Answers:

You are entering 3 times a record that has the exact same value for a field defined as UNIQUE. This is not allowed to do it at the database level, try to enter 3 different users with 3 different values ​​for the login field.

Answered By: Matteo Pasini