Как настроить отношение "один ко многим" в sqlalchemy?

Когда я пытаюсь создать запись во второй таблице, возникает исключение "null value in column 'user_id' of relation 'tokens' violates not-null constraint". Разве значение user_id не должно заполняться автоматически из первой таблицы?
  • 29 декабря 2023 г. 18:37
Ответы на вопрос 2
В SQLAlchemy отношение "один ко многим" может быть настроено с использованием связи ForeignKey и параметра backref.

Пример кода для настройки отношения "один ко многим" выглядит следующим образом:

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

Base = declarative_base()

class User(Base):
    __tablename__ = 'users'
    id = Column(Integer, primary_key=True)
    name = Column(String)
    tokens = relationship('Token', backref='user')

class Token(Base):
    __tablename__ = 'tokens'
    id = Column(Integer, primary_key=True)
    value = Column(String)
    user_id = Column(Integer, ForeignKey('users.id'), nullable=False)

```

В данном примере создаются две таблицы: "users" и "tokens". В таблице "tokens" внешний ключ "user_id" указывает на первичный ключ "id" в таблице "users".

Параметр backref в связи relationship('Token', backref='user') означает, что будет добавлено дополнительное свойство "user" в класс Token, которое будет ссылаться на связанного пользователя.

Когда вы создаете экземпляр класса Token, вы должны установить значение атрибута user, чтобы установить связанный объект User:

```python
user = session.query(User).first()
token = Token(value='some_value')
token.user = user
session.add(token)
session.commit()
```

При добавлении token в базу данных, user_id будет автоматически заполнен значением user.id.
Если вы хотите сделать так, что у одного пользователя может быть несколько токенов(one-to-many), то вам нужно в таблице Tokens создать этого пользователя(user). Также, если у вас первичные ключи, то лучше для наглядности указывать autoincrement=True. 

class Tokens(Base):
__tablename__ = 'tokens'

id: Mapped[int] = mapped_column(primary_key=True)
token: Mapped[str] = mapped_column(String(50))
user_id: Mapped[int] = mapped_column(BigInteger, ForeignKey('users.id'))
user: Mapped['User'] = relationship('User', back_populates='tokens')
Похожие вопросы