Обернуть импорт сообщений в транзакцию
def upload_messages(bytes_io: BytesIO, replace_existing_msgs: bool) -> dict:
context = {}
if not is_zipfile(bytes_io):
context["summary"] = "Обнаружены ошибки:"
context["errors"] = "Файл не является валидным zip архивом!"
return context
with ZipFile(bytes_io, mode="r") as zip_file:
imported_msgs_series = get_imported_msgs(
zip_file, "msgs_series.json", ImportedMessageSeries,
)
imported_text_msgs = get_imported_msgs(
zip_file, "texts_msgs.json", ImportedTextMessage,
)
imported_img_msgs = get_imported_msgs(
zip_file, "images_msgs.json", ImportedImageMessage,
)
imported_doc_msgs = get_imported_msgs(
zip_file, "docs_msgs.json", ImportedDocumentMessage,
)
if replace_existing_msgs:
series_pks, existing_series_pks = update_message_series(
imported_msgs_series, replace_existing_msgs,
)
for message_model in TgMessageSeries.message_models:
existing_series = existing_series_pks.values()
message_model.objects \
.filter(series__in=existing_series).delete()
else:
series_pks, existing_series_pks = create_message_series(
imported_msgs_series, replace_existing_msgs,
)
create_text_messages(
imported_text_msgs,
series_pks,
existing_series_pks,
replace_existing_msgs,
)
create_image_messages(
imported_img_msgs,
series_pks,
existing_series_pks,
replace_existing_msgs,
zip_file,
)
create_document_messages(
imported_doc_msgs,
series_pks,
existing_series_pks,
replace_existing_msgs,
zip_file,
)
context["summary"] = "Сообщения успешно загружены!"
context["upload_log"] = get_upload_messages_log(
series_pks,
existing_series_pks,
replace_existing_msgs,
)
return context
Так как при импорте новых сообщений возможно удаление старых из БД, то лучше все это делать в одной транзакции.