gpt4 book ai didi

python - 为什么 Flask SQL Alchemy 允许保存 None 主键?

转载 作者:太空宇宙 更新时间:2023-11-03 20:04:31 25 4
gpt4 key购买 nike

尽管主键为空,并且在主键字段中添加了 nullable=False(即使不需要添加它),但 Flask SQL Alchemy 仍会保存到数据库。

我正在分配 id,而不是使用正常的自动增量或 SQL Alchemy 附带的任何内容。

模型.py

class User(db.Model):
id = db.Column(db.Integer, primary_key=True, unique=True, nullable=False)

# passing in the ID manually
@classmethod
def new(cls, sender_id):
try:
db.create_all()
d = cls()
d.id = sender_id
return d
except Exception as e:
print('Error in User new:', e)

def insert(self):
try:
db.session.add(self)
db.session.commit()
print('INSERT OKAY')
except Exception as e:
print('RollBack', e)
db.session.rollback()

测试.py

#FLASK_ENV = 'dev_testing'
#----SETUP
# load env variables
def setup_testing_environment():
load_dotenv(find_dotenv(".env", raise_error_if_not_found=True)

#test setup testing DB
def create_test_app():
try:
app = Flask(__name__)
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
if os.environ['FLASK_ENV'] == 'development' or os.environ['FLASK_ENV'] == 'dev_testing':
setup_testing_environment()
app.config['SQLALCHEMY_DATABASE_URI'] = "sqlite:///:memory:"
return app
except Exception as e:
print('Error in create_test_app', e)


#---- ACTUAL TEST
def test_should_fail(unittest.testcase):
#assign DB and create context for test to run
app = create_test_app()
with app.app_context():
db.init_app(app)
# make ID value None;
user = User.new(None)
# <User id=None>
user.insert()
# fails - user *is* being added to DB
assert user in not db.session

#end test
db.session.remove()
db.drop_all()

没有发生回滚。 SQL Alchemy 没有显示任何错误。用户正在保存到数据库中,但由于没有 ID,因此无法查找。 User 表完全是空的。

为什么 SQL Alchemy 没有捕捉到这一点?我如何分配 ID 才能使其正常工作?

最佳答案

SQLAlchemy 的作者注意到 here那个

SQLAlchemy doesn't build this in as it defers to the DBAPI/database as the best and most efficient source of validation and coercion of values.

换句话说,执行 NOT NULL 约束,并将其留给数据库,因为它应该是这样的——数据库是唯一的事实来源。您当然可以实现 validation如果需要的话,也可以在您的模型中使用。

如果主键属性在 transient / pending 上将其设置为 None instance 本质上是一个无操作,与根本不设置具有相同的效果,因此使用默认值。默认设置为 autoincrementColumn“auto”,这意味着如果模型具有单列整数主键且没有显式默认值,它将接收自动递增行为。如果您启用日志记录,您将看到发出的查询类似于

INSERT INTO user DEFAULT VALUES

换句话说,在您的情况下,您的实例在刷新到数据库时会收到自动递增的主键值。如果您在db.commit()之后访问user.id,您将获得生成的主键值。

最后,

# fails - user *is* being added to DB 
assert user not in db.session

不会断言用户是否在数据库中,但如果它在当前 session 中,尽管在您的测试中,在调用之后它们确实也在数据库中db.commit(),它隐式地从 session 中刷新挂起状态。

关于python - 为什么 Flask SQL Alchemy 允许保存 None 主键?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59041840/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com