Django изменяет on_delete во время выполнения
История
Я делаю приложение Jurnal. В настоящее время работаю над синхронизацией на нескольких машинах. Я хочу синхронизировать модель за моделью, а не всю базу данных сразу. Я даже допускаю синхронизацию всего нескольких записей, изображений:
Текущая проблема, с которой я сталкиваюсь, заключается в замене данных модели на новые синхронизированные данные. У меня есть новая база данных для модели (не для всех моделей) в JSON.
Другие модели имеют ForeginKey
к изменяемым данным (с on_delete=CASCADE
). У меня есть отображение в виде dict
{old_pk : new_pk...}
. Я буду использовать его для обновления других объектов ForeginKey
на синхронизируемые объекты (чьи pk
изменятся).
Проблема
Я хочу удалить старую базу данных без CASCADE
удаления. Я хочу установить значение on_delete
на DO_NOTHING
временно, пока не закончу миграцию.
Примечание: ReadAt
код содержит:
read_by = models.ForeignKey(
Person,
on_delete=models.CASCADE, # change temporarily to DO_NOTHING at runtime
)
Изменяя on_delete
во время выполнения, я мог бы сделать:
# DELETE OLD DATA
ReadAt.on_delete=DO_NOTHING # pseudo code I want to achieve
Person.objects.all().delete() # without code above, this deletes all ReadAt
# LOAD NEW DATA
with open("person_file.json", mode="w+", encoding="utf-8") as myfile:
myfile.write(json.dumps(data_new_server))
call_command("loaddata", "person_file.json")
# Then fix the PKs of ReadAt with a mapping I have made
ReadAt.on_delete=CASCADE # pseudo code, change back
# ideally check the integrity of ReadAt data now
Альтернатива
Я думал об этом, но застрял:- Найдите максимальное значение импортируемого пк MAX_PK.
- Измените все записи PKs в Person (и FK в ReadAt), добавьте к ним MAX_PK.
- Я не знаю, как это сделать. pk кажется нередактируемым, Это не работает: https://stackoverflow.com/a/77775898/5057078
- Импортируйте новые данные (старые и новые данные не должны пересекаться).
- Измените PK ReadAt со old_PK на new_PK.
- Удалите все Person, чей PK >= MAX_PK, для них нет ForeginKeys после предыдущего шага.
Я думал об этом, но это кажется более сложным, чем то, что я хочу. Это происходит от альтернативы в вопросе:
Дополнительные ограничения на решение:
- перенумеруйте пк после завершения работы .
- Используются только две машины, поэтому они будут синхронизироваться только между ними.
Решение:
- Найти максимум текущего пк MAX_PK_CURRENT.
- Найдите максимум импортированного пк MAX_PK_IPORTED.
- MAX_PK = max(MAX_PK_CURRENT, MAX_PK_IPORTED)
- Дублировать записи о персонах, дубликаты будут иметь PK=original_pk + MAX_PK
- Измените PK в ReadAt со old_PK на duplicate_PK.
- Удалите все Person, чей PK < MAX_PK, к ним нет ForeginKeys после предыдущего шага.
- Импортируйте новые данные (дубликат и импортированные данные не должны пересекаться).
- Измените PK ReadAt с duplicated_PK на new_PK.
- Удалите все Person, чей PK >= MAX_PK, для них нет ForeginKeys после предыдущего шага.
Я попробую реализовать это позже.