我正在用Flask创建一个记分API。尽管经过数小时的谷歌搜索,但我仍无法使数据库正常工作。
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///test.db"
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False
db = SQLAlchemy(app)
class Person (db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(64), nullable=False)
first_name = db.Column(db.String(64), nullable=False)
last_name = db.Column(db.String(64), nullable=False)
birthdate = db.Column(db.String(64), nullable=True)
description = db.Column(db.String(256), nullable=True)
match1 = db.relationship("Match", back_populates="person")
match2 = db.relationship("Match", back_populates="person2")
class Match (db.Model):
id = db.Column(db.Integer, primary_key=True)
game = db.Column(db.String(64), db.ForeignKey("game.id"))
place = db.Column(db.String(64), nullable=True)
time = db.Column(db.String(32), nullable=True)
player1_id = db.Column(db.Integer, db.ForeignKey("person.id"))
player2_id = db.Column(db.Integer, db.ForeignKey("person.id"))
player1_score = db.Column(db.Float, nullable=False)
player2_score = db.Column(db.Float, nullable=False)
comment = db.Column(db.String(256), nullable=True)
games = db.relationship("Game", back_populates="matches")
person = db.relationship(
"Person",
foreign_keys="Match.player1_id",
back_populates="match1"
)
person2 = db.relationship(
"Person",
foreign_keys="Match.player2_id",
back_populates="match2"
)
class Game (db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String, nullable=True)
score_type = db.Column(db.Integer, nullable=False)
matches = db.relationship("Match", back_populates="games")
在Python shell中:
>>> from app import *
>>> db.create_all()
>>> pers1 = Person(username="username",first_name="user",last_name="name")
Traceback (most recent call last):
File "/home/USERNAME/pythonvenvs/pwp_3.6/lib/python3.6/site-packages/sqlalchemy/orm/relationships.py", line 2354, in _determine_joins
consider_as_foreign_keys=consider_as_foreign_keys,
File "<string>", line 2, in join_condition
File "<string>", line 2, in _join_condition
File "/home/USERNAME/pythonvenvs/pwp_3.6/lib/python3.6/site-packages/sqlalchemy/util/deprecations.py", line 130, in warned
return fn(*args, **kwargs)
File "/home/USERNAME/pythonvenvs/pwp_3.6/lib/python3.6/site-packages/sqlalchemy/sql/selectable.py", line 923, in _join_condition
a, b, constraints, consider_as_foreign_keys
File "/home/USERNAME/pythonvenvs/pwp_3.6/lib/python3.6/site-packages/sqlalchemy/sql/selectable.py", line 1040, in _joincond_trim_constraints
"join explicitly." % (a.description, b.description)
sqlalchemy.exc.AmbiguousForeignKeysError: Can't determine join between
'person' and 'match'; tables have more than one foreign key constraint
relationship between them. Please specify the 'onclause' of this join
explicitly.
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<string>", line 2, in __init__
File "/home/USERNAME/pythonvenvs/pwp_3.6/lib/python3.6/site-packages/sqlalchemy/orm/instrumentation.py", line 373, in _new_state_if_none
state = self._state_constructor(instance, self)
File "/home/USERNAME/pythonvenvs/pwp_3.6/lib/python3.6/site-packages/sqlalchemy/util/langhelpers.py", line 855, in __get__
obj.__dict__[self.__name__] = result = self.fget(obj)
File "/home/USERNAME/pythonvenvs/pwp_3.6/lib/python3.6/site-packages/sqlalchemy/orm/instrumentation.py", line 199, in _state_constructor
self.dispatch.first_init(self, self.class_)
File "/home/USERNAME/pythonvenvs/pwp_3.6/lib/python3.6/site-packages/sqlalchemy/event/attr.py", line 297, in __call__
fn(*args, **kw)
File "/home/USERNAME/pythonvenvs/pwp_3.6/lib/python3.6/site-packages/sqlalchemy/orm/mapper.py", line 3341, in _event_on_first_init
configure_mappers()
File "/home/USERNAME/pythonvenvs/pwp_3.6/lib/python3.6/site-packages/sqlalchemy/orm/mapper.py", line 3229, in configure_mappers
mapper._post_configure_properties()
File "/home/USERNAME/pythonvenvs/pwp_3.6/lib/python3.6/site-packages/sqlalchemy/orm/mapper.py", line 1947, in _post_configure_properties
prop.init()
File "/home/USERNAME/pythonvenvs/pwp_3.6/lib/python3.6/site-packages/sqlalchemy/orm/interfaces.py", line 196, in init
self.do_init()
File "/home/USERNAME/pythonvenvs/pwp_3.6/lib/python3.6/site-packages/sqlalchemy/orm/relationships.py", line 1854, in do_init
self._setup_join_conditions()
File "/home/USERNAME/pythonvenvs/pwp_3.6/lib/python3.6/site-packages/sqlalchemy/orm/relationships.py", line 1934, in _setup_join_conditions
can_be_synced_fn=self._columns_are_mapped,
File "/home/USERNAME/pythonvenvs/pwp_3.6/lib/python3.6/site-packages/sqlalchemy/orm/relationships.py", line 2239, in __init__
self._determine_joins()
File "/home/USERNAME/pythonvenvs/pwp_3.6/lib/python3.6/site-packages/sqlalchemy/orm/relationships.py", line 2399, in _determine_joins
"foreign key reference to the parent table." % self.prop
sqlalchemy.exc.AmbiguousForeignKeysError: Could not determine join condition between parent/child tables on relationship Person.match1
- there are multiple foreign key paths linking the tables. Specify the 'foreign_keys' argument, providing a list of those columns which
should be counted as containing a foreign key reference to the parent table.
如何获取Match.player1_id和Match.player2_id来引用Person.id?网络上有很多例子,但我都没有成功。我应该使用backref还是back_populates?
我已经尝试过让Person表中的关系只有一种,其中foreign_keys参数是一个列表。我也无法正常工作。
答案 0 :(得分:0)
我尝试了您的示例,这是如何使它工作的(但我不确定这是否是您想要实现的目标)。
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///test.db"
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False
db = SQLAlchemy(app)
class Person (db.Model):
__tablename__ = 'person'
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(64), nullable=False)
first_name = db.Column(db.String(64), nullable=False)
last_name = db.Column(db.String(64), nullable=False)
birthdate = db.Column(db.String(64), nullable=True)
description = db.Column(db.String(256), nullable=True)
match1 = db.relationship(
"Match",
foreign_keys="Match.player1_id",
backref ="player1"
)
match2 = db.relationship(
"Match",
foreign_keys="Match.player2_id",
backref="player2"
)
class Match (db.Model):
__tablename__ = 'match'
id = db.Column(db.Integer, primary_key=True)
game = db.Column(db.Integer, db.ForeignKey("game.id"))
place = db.Column(db.String(64), nullable=True)
time = db.Column(db.String(32), nullable=True)
player1_id = db.Column(db.Integer, db.ForeignKey("person.id"))
player2_id = db.Column(db.Integer, db.ForeignKey("person.id"))
player1_score = db.Column(db.Float, nullable=False)
player2_score = db.Column(db.Float, nullable=False)
comment = db.Column(db.String(256), nullable=True)
games = db.relationship("Game", back_populates="matches")
class Game (db.Model):
__tablename__ = 'game'
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String, nullable=True)
score_type = db.Column(db.Integer, nullable=False)
matches = db.relationship("Match", back_populates="games")