在Flask炼金术中建立多重关系

2024-09-28 13:10:11 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图做一个游戏表,每个游戏应该指向两个玩家或用户。在

这是我现在掌握的密码。我正在使用sql炼金术

UserGame = db.Table('UserGame',
    db.Column('game_id',db.Integer,db.ForeignKey('game.id')),
    db.Column('user_id',db.Integer,db.ForeignKey('user.id')),
    )

class User(db.Model):
    __tablename__ = 'User'
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(80), unique=True)
    email = db.Column(db.String(120), unique=True)
    games = db.relationship('Game', secondary=UserGame, backref='players')

    def __init__(self, username, email):
        self.username = username
        self.email = email
    def __repr__(self):
        return '<User %r>' % self.username

class Game(db.Model):
    __tablename__ = 'Game'
    id = db.Column(db.Integer, primary_key=True)
    player1 = db.Column(db.Integer,db.ForeignKey('User.id')
    player2 = db.Column(db.Integer,db.ForeignKey('User.id')
    ended = db.Column(db.Boolean)
    winner_username = db.Column(db.String(80),db.ForeignKey('User.username'))

但是,当我试图创建一个用户时,我得到了以下错误:

^{pr2}$

有什么想法吗?在


Tags: 用户selfidgametrue游戏dbstring
1条回答
网友
1楼 · 发布于 2024-09-28 13:10:11

M到N通向关联类

一旦找到M:N关系,就要使用所谓的关联类来描述这种关系。在

在你的例子中,你有两个玩家之间的关系,这个关联的意思是“他们一起玩的游戏”。在

最小关联类描述:

  • 某些类的两个实例之间的关系
  • 没有附加数据绑定到给定的关联

可能有三元甚至更复杂的联系,但这些是相当罕见的。在

在某些情况下,这就是博弈的例子,我们可能会在关联中添加一些额外的数据(比如结果,谁是赢家等等)。在

在描述同一类的两个实例之间的关联时不存在概念上的问题。在

sqlalchemy中关联类的建模

在sqlalchemy中有三种建模关联类的方法

辅助表

在sqlalchemy中,简单的M:N关系通常由所谓的辅助表建模。不幸的是,这里并不是这样,因为我们需要在已知的关联上附加额外的信息。在

关联类

这就是你的方法。接下来是代码。在

关联代理

有一些高级技术,使用association_proxy,可能会隐藏association类实例,但我们并不需要这些(实际上,我们希望在模型中看到游戏的概念)。在

在模型.py-使用过的类

下面的例子模拟了团队,这些团队可能一起玩游戏。每场比赛都在东道主进行,另一队被视为客人。我们每场比赛都记录一个分数。在

这个例子应该很容易为您的场景修改。在

from sqlalchemy import Column, Integer, String, ForeignKey
from sqlalchemy.orm import relationship
from sqlalchemy.ext.declarative import declarative_base

Base = declarative_base()

class Team(Base):
    __tablename__ = "team"
    id = Column(Integer, primary_key=True)
    name = Column(String(40))

    def __init__(self, name):
        self.name = name

    def __repr__(self):
        return "<Team: {self.name}>".format(self=self)

class Game(Base):
    __tablename__ = "game"
    host_id = Column(Integer, ForeignKey("team.id"), primary_key=True)
    guest_id = Column(Integer, ForeignKey("team.id"), primary_key=True)
    host_score = Column(Integer)
    guest_score = Column(Integer)

    def __init__(self, host, guest, host_score, guest_score):
        self.host = host
        self.guest = guest
        self.host_score = host_score
        self.guest_score = guest_score
    host = relationship(Team, lazy="joined", foreign_keys="Game.host_id", backref="games_ashost")
    guest = relationship(Team, lazy="joined", foreign_keys="Game.guest_id", backref="games_asguest")

    def __repr__(self):
        templ = "<Game: {self.host.name} vs {self.guest.name} score: {self.host_score}:{self.guest_score}>" 
        return templ.format(self=self)

除了设置类Game,为这个类定义host和{}肉信息很重要。为了这个目的。在

当我们将同一类的两个实例关联起来时,sqlalchemy很难找到哪些类属性与host链接,哪些与{}链接。为此,relationship必须使用foreign_keys,它可能以数组或外键字符串的形式使用。(这对我来说是最困难的部分,因为例子不能说明这一点)。在

relationship中的backref向partnering类添加新属性,因此backref="games_ashost将为每个Team添加一个属性Team().games_ashost。在

玩弄模特儿

导入所需内容

^{pr2}$

准备引擎和会话

>>> engine = create_engine("sqlite://")
>>> Base.metadata.create_all(engine)
>>> session = Session(engine)

创建团队阿尔法,贝塔,伽马,三角洲

>>> alfa = Team("alfa")
>>> beta = Team("beta")
>>> gama = Team("gama")
>>> delta = Team("delta")
>>> alfa
<Team: alfa>
>>> beta
<Team: beta>
>>> gama
<Team: gama>
>>> delta
<Team: delta>

将它们存储在数据库中

>>> session.add_all([alfa, beta, gama, delta])
>>> session.commit()

实例化游戏(getween Alfa和Beta、Alfa和Gama)并将它们存储在数据库中

>>> game_ab = Game(alfa, beta, 0, 0)
>>> game_ab
<Game: alfa vs beta score: 0:0>
>>> game_ag = Game(alfa, gama, 0, 0)
>>> session.add_all([game_ab, game_ag])
>>> session.commit()

探索团队的可用属性

>>> alfa.games_ashost
[<Game: alfa vs beta score: 0:0>, <Game: alfa vs gama score: 0:0>]
>>> alfa.games_asguest
[]
>>> beta.games_ashost
[]
>>> beta.games_asguest
[<Game: alfa vs beta score: 0:0>]
>>> gama.games_ashost
[]
>>> gama.games_asguest
[<Game: alfa vs gama score: 0:0>]
>>> gama
<Team: gama>

探索游戏属性

>>> game_ab.host
<Team: alfa>
>>> game_ab.guest
<Team: beta>

相关问题 更多 >

    热门问题