Как я могу вставить новую запись в ассоциативную таблицу о всех существующих данных с помощью SQLAlchemy - PullRequest
0 голосов
/ 13 декабря 2018

Среда: python3.7, SQLAlchemy1.3, SQLite3.22

Я определил 2 таблицы и 1 ассоциативную таблицу, как показано ниже.

# associative table
taggings = Table('taggings', Base.metadata, 
    Column('id', Integer, primary_key=True),
    Column('article_id', Integer, ForeignKey('articles.id'), nullable=False),
    Column('tag_name', Integer, ForeignKey('tags.name'), nullable=False),
)

# mapper about article master
class Article(Base):
    __tablename__ = 'articles'
    id = Column(Integer, primary_key=True)
    ...
    tags = relationship('Tag', secondary=taggings, backref='articles')

# mapper about tag master
class Tag(Base):
    __tablename__ = 'tags'
    name = Column(String, primary_key=True)

Теперь я хочу иметь возможность создаватьНовая статья, которая помечена с любыми существующими тегами.Итак, я попытался как ...

new_one = Article(**payload.article)
new_one.tags = [Tag(name=x) for x in payload.tags]  # these tags are already stored in database.
sesion.add(new_one)
session.flush()

И протестировать его, но я получил ошибку об УНИКАЛЬНО ограничении.Подробности здесь.

*** sqlalchemy.exc.IntegrityError: (sqlite3.IntegrityError) Не удалось выполнить ограничение UNIQUE: tags.name [SQL: 'INSERT INTO tags (name) ЗНАЧЕНИЯ (?)'][параметры: (('x',), ('a',))] (Справочная информация об этой ошибке: http://sqlalche.me/e/gkpj)

Я думаю, session.add всегда пытается вставить, когда родительский элементимеет детей, и «дети», которые здесь представлены, могут быть Tag. Но я действительно хочу создать только новые записи на основе таблицы taggings, ссылающейся на новые данные статьи и любые существующие теги.

Я прочитало каскаде в официальном документе , и я попытался удалить опцию save-update из relationship(), но не решил.

Пожалуйста, как решить эту проблему.

1 Ответ

0 голосов
/ 14 декабря 2018

Учитывая ваш ответ на мой вопрос, вы должны добавить проверку, если тег из payload еще не находится в базе данных.Так должно быть что-то вроде этого:

new_one = Article(**payload.article)
tags = []
for tag_name in payload.tags:
    tag = session.query(Tag).filter_by(name=tag_name).first()
    # tag will be None if it does not exist in the database
    tags.append(tag if tag else Tag(name=tag_name))
new_one.tags = tags
sesion.add(new_one)
session.flush()

Так что теперь вы будете использовать существующий тег, если он уже есть в базе данных, или создаете новый, если его нет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...