我一直在搜索StackOverflow问题并阅读SQLAlchemy和Flask-SQLAlchemy文档,但仍然没有想出如何使反射工作(对SQLAlchemy来说还是新手)。
当我尝试使用引擎映射表时,我收到错误" sqlalchemy.exc.ArgumentError:Mapper Mapper | User | user无法为映射表组装任何主键列' user&# 39;&#34 ;. 尽管如此,用户还有专栏' id'作为数据库中的主键。我不确定我是否还需要先做其他事情。我曾经想过,如果我能反思,它会自动给出以数据库列命名的User模型类属性,我不必手动定义它们。
这是我到目前为止拼凑的代码:
from flask_sqlalchemy import SQLAlchemy
from sqlalchemy.orm import mapper
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = "mysql+pymysql://" + dbUser + ":" + dbPass + "@" + dbAddress + ":3306/" + dbName
app.config["SQLALCHEMY_ECHO"] = True
db = SQLAlchemy(app)
engine = db.engine
meta = db.metadata
现在有了这个,我知道db会给我一个很好的数据库会话。我还不确定我在引擎和元数据方面做错了什么。我已经看到引擎被用来以不同的方式创建上下文,但我想我是用这条线创建的(从上面开始):
db = SQLAlchemy(app)
这是我尝试反映模特课程的地方:
class User(db.Model):
try:
self = db.Model.metadata.tables('user', metadata)
#self = Tadb.Model.metadata.tables('user', meta, autoload=True, autoload_with=engine, extend_existing=True)
#Table('user', metadata, autoload_with=engine, extend_existing=True)
#self = Table('user', meta, autoload_with=engine, extend_existing=True)
#self.metadata.reflect(extend_existing=True, only=['user'])
except Exception as e:
print("In init User(): failed to map table user - " + str(e))
我在这一行(从上面)得到映射器错误:
self = db.Model.metadata.tables('user', metadata)
我也尝试过其他行,但它似乎不知道Table是什么......我有Flask-SQLAlchemy 2.3.2。
我在这里犯了任何明显的错误吗?
答案 0 :(得分:2)
您可以尝试反映id
字段(或数据库中的真实姓名)以及代码中需要的所有字段:
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(50), nullable=False)
答案 1 :(得分:2)
这花费了我几天的努力,阅读了超过30个StackOverflow Q / As并在SQLAlchemy和Flask-SQLAlchemy文档中删除了很多兔子洞,尝试并丢弃了相当多的代码片段。这就是我拼凑在一起的东西。注意:这是使用Flask-MySQL版本2.3.2。
我认为Flask-SQLAlchemy在应用初始化后提供引擎和元数据是相当不寻常的,但是他们页面上的文档让他们从SQLAlchemy导入不同的引擎和元数据模块。 不仅如此,他们还导入了一个单独的会话引擎,我刚刚使用Flask初始化的数据库上下文来获取会话,并且它可以工作。
不仅如此,但是这样做可以使用Flask-SQLAlchemy无法实现StackOverflow状态下99%的Q / As - 自动化/反映数据库表。也就是说,我根本不需要在类上声明属性,这些属性直接来自数据库。
以下是代码:
import requests
import json
from flask import Flask, render_template, request, redirect, jsonify
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
#The file I am importing below is named config and is in the same folder as app.py.
#It has json formatted text and looks like this (without the '#' signs, and remove the <> signs that surround
#the places you need to insert the db address, username, password, and database name (instance name -
#database servers can have multiple databases on them, each one is called an instance / has a different name))
#{
#"dbAddress" = "<some IP or URL to your database server>",
#"dbName" = "<database name>",
#"dbUser" = "<database user name>",
#"dbPass" = "<dbPass>"
#}
with open('config') as data_file:
data = json.load(data_file)
dbAddress = data["dbAddress"]
dbName = data["dbName"]
dbUser = data["dbUser"]
dbPass = data["dbPass"]
app.config['SQLALCHEMY_DATABASE_URI'] = "mysql+pymysql://" + dbUser + ":" + dbPass + "@" + dbAddress + ":3306/" + dbName
app.config["SQLALCHEMY_ECHO"] = True
db = SQLAlchemy(app)
db.Model.metadata.reflect(bind=db.engine)
class User(db.Model):
__tablename__ = 'user'
def __init__(self, db, username, password, email):
try:
self = db.session.query(User).filter(User.username==username) #.one()
except Exception as e:
print("In init User(): Failed to load an existing user into the model for user '" + username + "' " + str(e))
self.username=username
self.password=password
self.emailAddress=emailAddress
try:
db.session.add(self)
db.session.commit()
print("In init User(): Inserted or updated user '" + username + "'")
return True
except Exception as e:
print("In init User(): insert or update exception on user '" + username + "': " + str(e))
return False
def delete(db, userid):
try:
self = db.session.query(User).filter(User.id == userid).one()
db.session.delete(self)
db.session.commit()
except Exception as e:
print("In User.delete(): failed to delete userid '" + self.id + "', username '" + self.username + "': " + str(e))
def getAllUsers(db):
return db.session.query(User).all()
#Setting this to blank would "logout" the user.
#This is because csrf_protect prevents POST requests from going through other
#than login and signup.
def updateSessionToken(db, userid, token):
try:
self = db.session.query(User).filter(User.id == userid).one()
self.sessionToken = token
db.session.add(self)
db.session.commit()
print("In User.updateSessionToken(): Successfully updated the token for userid '" + userid + "'.")
return True
except Exception as e:
print("In User.updateSessionToken() failed to update token: " + str(e))
return False
def checkSessionToken(db, userid, givenToken):
try:
user = db.session.query(User).filter(User.id == userid).one()
except Exception as e:
print("In checkSessionToken(): issue looking up userid: " + userid + ": " + str(e))
if user:
if user.sessionToken == givenToken:
print("In User.checkSessionToken(): token match confirmed for userid '" + user.id + "', username '" + user.username + "'.")
return True
else:
print("In checkSessionToken() - token and given token do not match")
else:
print("In checkSessionToken() - user by given id '" + userid + "' not found.")
return False