Sqlalchemy 炼金术中一对一关系的实现

Sqlalchemy 炼金术中一对一关系的实现,sqlalchemy,flask-sqlalchemy,Sqlalchemy,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) ema

我是一个没有经验的程序员。我想在用户和货币之间添加一对一关系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 = ?

    # ...
我想要实现的是为每个
用户.id
分配一个
货币.id
(一对一)

我想征求一些建议,最好的做法是什么

考虑到这个问题后,我有如下想法:

  • 与uselist的关联表=假关系
  • 创建新类CurrencyDefault(id、用户id、货币id)
  • 或者也许有其他更好的方法来实现它
  • 我很好奇你对这个问题的看法

    实施解决方案: 这就是我的课程现在的样子:

    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,
        )
    
  • 我发现的第一个问题是,我可以将
    其他用户创建的
    Currency.id
    对象设置为
    Currency\u default\u choice
    。如何将
    currency\u default\u选项
    仅限于此
    用户创建的

  • User
    类(
    currency\u default\u choice=db.Column(db.Integer,b.ForeignKey('currency.id'))
    )中设置具有
    ForeignKey
    的关系与以下设置有什么区别:

  • 并在
    用户
    侧设置此关系:

    class User(db.Model):
    # ...
        currency_default = db.relationship(
              'Currency',
              foreign_keys='User.currency_default_choice',
              backref='currency_default',
              uselist=False,
        )
    
    公元2年。在我看来,这两种方法之间没有区别,因为
    backref
    参数暗示了
    双向行为
    ,所以我是否将
    db.relationship()
    放在
    User
    Currency
    类中并不重要。对吗

  • 使用PythonShell I为
    用户.currency\u默认值添加了值

  • 这听起来像是一种多对一的关系。(许多
    用户
    共享相同的
    货币
    选择。因此在
    用户
    模型中会有一个
    货币id
    。不,这是一对一的,因为每个
    用户
    都可以使用唯一id创建自己的
    货币
    ,并且只能访问他创建的货币。
    uselist False
    不是他通常的做法是——有一个关于SQLAlchemy的例子用于设置。我会将默认值存储在用户端,因为这样会更清楚(user.default\u currency\u choice),节省一点空间,并保存一个查询以每次计算出默认值。
    class User(db.Model):
    # ...
        currency_default = db.relationship(
              'Currency',
              foreign_keys='User.currency_default_choice',
              backref='currency_default',
              uselist=False,
        )
    
    >>> 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
    
    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>))