首页 > 解决方案 > Flask SQLAlchemy中一对一关系的实现

问题描述

我是一个没有经验的程序员。我想在用户和货币之间添加一对一的关系 CurrencyDefault(该值将分配给 FlaskForm 中的字段):

class User(UserMixin, db.Model):
    id = db.Column(db.Integer, db.Sequence('user_id_seq'), primary_key=True)
    username = db.Column(db.String(64), index=True, unique=True)
    email = db.Column(db.String(64), index=True, unique=True)
    pswd_hash = db.Column(db.String(128))
    expenses = db.relationship('Expense', backref='user')
    currency = db.relationship('Currency', backref='user')
    curr_default = ?

    # ...

class Currency(db.Model):
    id = db.Column(db.Integer, db.Sequence('expense_id_seq'), primary_key=True)
    abbr = db.Column(db.String(10))
    name = db.Column(db.String(64))
    user_id = db.Column(db.Integer, db.ForeignKey('user.id'))
    default = ?

    # ...

我想要实现的是分配给每个user.idcurrency.id(一对一)

我想请教一些建议,什么是最好的制作方法。

在考虑了这个问题后,我有一些想法,例如:

  1. 具有 uselist=False 关系的关联表,
  2. 创建一个新类 CurrencyDefault(id, user_id, currency_id),
  3. 或者也许还有其他更好的方法来实现它?

我很好奇你对这个问题的看法。

实施解决方案:

这就是我的课程现在的样子:

class User(UserMixin, db.Model):
    id = db.Column(db.Integer, db.Sequence('user_id_seq'), primary_key=True)
    username = db.Column(db.String(64), index=True, unique=True)
    email = db.Column(db.String(64), index=True, unique=True)
    pswd_hash = db.Column(db.String(128))
    currency_default_choice = db.Column(db.Integer, b.ForeignKey('currency.id'))
    expenses = db.relationship('Expense', backref='user')
    currency = db.relationship('Currency', backref='user', foreign_keys="Currency.user_id")
    # currency_default = db.relationship(
    #       'Currency',
    #       foreign_keys='User.currency_default_choice',
    #       backref='currency_default',
    #       uselist=False,
    # )

# ...

class Currency(db.Model):
    id = db.Column(db.Integer, db.Sequence('expense_id_seq'), primary_key=True)
    abbr = db.Column(db.String(10), b.ForeignKey('currency_official_abbr.abbr'))
    name = db.Column(db.String(64))
    user_id = db.Column(db.Integer, db.ForeignKey('user.id'))
    currency_default = db.relationship(
            'User',
            foreign_keys='User.currency_default_choice',
            backref='currency_default',
            uselist=False,
    )
  1. 我发现的第一个问题是我可以设置Currency.idother_useras创建的对象currency_default_choice。如何currency_default_choice仅限于<Currency>由 this 创建的user

  2. foreign keyUser类 ( ) 中设置关系currency_default_choice = db.Column(db.Integer, b.ForeignKey('currency.id'))与:

class Currency(db.Model):
# ...
currency_default = db.relationship(
            'User',
            foreign_keys='User.currency_default_choice',
            backref='currency_default',
            uselist=False,
    )

并将这种关系设置User为:

class User(db.Model):
# ...
    currency_default = db.relationship(
          'Currency',
          foreign_keys='User.currency_default_choice',
          backref='currency_default',
          uselist=False,
    )

广告 2。在我看来,这两种方式之间没有区别,因为backref参数暗示bidirectional behavior,所以我是否放置db.relationship()User上课Currency都没有关系。这是对的吗?

  1. 使用 Python shell 我为User.currency_default
>>> app = create_app()
>>> app.app_context().push()
>>> admin = User.query.filter_by(username='admin').first()
<User(id= 1, username = admin, email = admin@admin.com)
>>> currency = Currency.query.filter_by(user=admin)
>>> currency
<flask_sqlalchemy.BaseQuery object at 0x03EA05D0>
>>> currency[0].id
1
>>> admin.currency_default = currency[0]
>>> db.session.commit()
>>> currency[0].currency_default
<User(id= 1, username = admin, email = admin@admin.com)
>>> admin.currency_default_choice
1

然后在运行后使用管理面板flask run 我想删除引入的值,但我得到了我不明白的错误。(Currency.currency_default)为什么,(User.currency_default)和之间存在循环依赖(User.currency)?我不明白发生了什么。如何解决?

sqlalchemy.exc.CircularDependencyError: Circular dependency detected. 
(ProcessState(OneToManyDP(Currency.currency_default), 
<Currency at 0x46542b0>, delete=False), 
ProcessState(ManyToOneDP(User.currency_default), 
<User at 0x4669b10>, delete=False), 
SaveUpdateState(<Currency at 0x46542b0>), 
ProcessState(OneToManyDP(User.currency), <User at 0x4669b10>, delete=False), 
SaveUpdateState(<User at 0x4669b10>))

标签: sqlalchemyflask-sqlalchemy

解决方案


推荐阅读