Массовая вставка в несколько таблиц с использованием SQLAlchemy ORM - PullRequest
0 голосов
/ 15 декабря 2018

Я пытаюсь выполнить массовую вставку в 2 таблицы, используя Flask-SQLAlchemy.2 таблицы:

  1. таблица автора: PK author_id (автоинкремент)
  2. таблица книг: PK book_id (ai), FK author_author_id

В теле JSON у меня есть список словарей.Каждая запись в словаре содержит некоторую информацию об авторе и информацию о книге.Примерно так: может быть отправлено гораздо больше словарей за один раз:

[
    {
        "author_first_name": "John",
        "author_last_name": "Doe",
        "author_yob": "1988",
        "book_name": "Mournings of a nun",
        "book_genre": "Drama"
    },
    {
        "author_first_name": "Jane",
        "author_last_name": "Doe",
        "author_yob": "1987",
        "book_name": "Need for speed",
        "book_genre": "Action"
    }
]

В настоящее время я перебираю каждый словарь, вставляю данные в таблицу авторов, а затем в таблицу книг.Когда я вставляю в таблицу автора и фиксирую, я получаю первичный ключ, который является author_id.Это внешний ключ для моей таблицы книг.

Я повторяю этот шаг для каждой записи в этом списке.Есть ли способ выполнить массовую вставку, чтобы в случае сбоя любой вставки все откатывалось, и в моей базе данных не было противоречивых данных?Таким образом, если в JSON выше 15 словарей, если у 12-го есть какие-то недопустимые данные или база данных выходит из строя, я хочу, чтобы ни одна из данных, отправленных в JSON, не была опубликована в AWS RDS.Ниже «результаты» относятся к JSON, который я упомянул выше.

    @classmethod
    def post_to_database(cls, results):
        for result in results:
            BookModel.post_entry_to_database(result)


    @classmethod
    def post_entry_to_database(cls, result):
        BookModel.insert_author_entry(result)
        author_id = BookModel.get_author_id(result)
        BookModel.insert_book_entry(author_id, result)


    @classmethod
    def insert_book_entry(cls, author_id, result):
        book_data = BookModel(result["testname"], result["result"], author_id)
        db.session.add(book_data)
        db.session.commit()

Аналогично, у меня также есть insert_author_entry.

Спасибо, Адитья

1 Ответ

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

Вы можете использовать flush() для сброса изменений в базе данных, что обновит ваше поле первичного ключа.

Из документов SqlAlchemy: flush

Операции с базой данных будут выполняться в текущем транзакционном контексте и не влияют на состояние транзакции, если только не происходит ошибка, и в этом случае вся транзакция откатывается.Вы можете вызывать flush () столько раз, сколько захотите в транзакции, чтобы переместить изменения из Python в буфер транзакций базы данных.

При вызове flush база данных поддерживает ваши операции CRUD как ожидающие транзакции.и не сохраняются постоянно, пока база данных не получит COMMIT для этой текущей транзакции.Это произойдет, когда вы впоследствии позвоните commit().

...