Я неопытный программист. Я хотел бы добавить отношение «один к одному» 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.id
один currency.id
(один к одному)
Я хотел бы спросить совета, как лучше всего это сделать.
После рассмотрения проблемы у меня есть некоторыетакие идеи, как:
- Таблица ассоциации с uselist = Ложные отношения,
- Создать новый класс CurrencyDefault (id, user_id, currency_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
объект, созданный other_user
, как currency_default_choice
. Как ограничить currency_default_choice
только <Currency>
, созданным этим user
?
В чем разница между установочными отношениями, имеющими foreign key
в User
классе (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,
)
Ad.2. Мне кажется, что между этими двумя способами нет никакой разницы, потому что параметр backref
подразумевает bidirectional behavior
, поэтому не имеет значения, поместил ли я db.relationship()
в класс User
или Currency
. Это правильно?
Используя оболочку Python, я добавил значение к
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>))