Автор оригинала: Apoorva Somani.
Обо мне
Я инженер полного стека, который работает с Django уже почти два года.
Проблема, которую я хотел решить
У нас было несколько действий, когда необходимо было скопировать данные из одной модели или создать клон записей в одной и той же модели. Во всех таких действиях у нас были условия, при которых иногда приходилось копировать только несколько полей, или некоторые поля приходилось игнорировать, или для некоторых полей требовалось предоставить какое-то другое значение. Это также означало, что нам нужно было написать один и тот же код для разных типов полей. Каждый раз, когда нам приходилось выполнять клонирование или копирование, мы заканчивали тем, что писали много кода, который был не только избыточным, но и сложным в обслуживании и масштабировании.
Что такое Универсальная утилита клонирования?
Я решил разработать универсальную утилиту клонирования, которая могла бы копировать данные из любого объекта модели в любой другой объект модели. Он может копировать все виды полей в Django — от простого CharField
до сложного TreeForeignKey
. Вы можете указать, какое поле необходимо скопировать или клонировать, любое значение, которое необходимо установить, или любые поля, которые необходимо игнорировать. Кроме того, вы можете выполнить массовое копирование и bulkclone, чтобы оптимизировать нагрузку на создание базы данных.
Технический стек
Я использовал Python и Django, так как мы использовали это в нашем проекте. Я говорю Python и Django, потому что эта утилита была исправлена на Django models
class и использовала некоторые методы, определенные с помощью models
и полей
классов внутри.
Процесс создания утилиты генетического клонирования
Первым и главным шагом в написании утилиты клонирования было определение того, как различные типы полей, доступных в Django, могут быть скопированы из одного объекта модели в другой. Некоторые поля можно просто скопировать с помощью метода setattr
, но некоторые поля, такие как ManyToMany
field и TreeForeignKey
, требуют некоторой обработки, прежде чем их можно будет скопировать.
Затем я посмотрел, как я могу настроить значения во время копирования, т. Е. Как я могу предоставить какое-то другое значение полю вместо значения поля исходного объекта. Кроме того, я добавил функцию игнорирования некоторых полей при копировании, для которых будет выбрано значение по умолчанию, определенное в модели.
После того, как копирование всех полей заработало, я посмотрел на оптимизацию запросов, которые были сделаны к базе данных. Я связал это с массовым копированием/клонированием.
Я сделал это, потому что копирование большинства полей не было дружественным к базе данных или не могло работать с bulk_create
. Например, наиболее распространенный способ добавления файлов с использованием Content File
object для FileField
требовал вызова базы данных исключительно для этого поля.
У этого также была другая проблема, связанная с тем, что файл был сначала загружен в память на сервере. Я решил эту проблему, сделав вызов API копирования в Amazon S3 (это было то, что мы использовали для хранения файлов), чтобы скопировать файлы в S3 и просто вернуть нам путь к файлу. Если у нас есть путь к файлу нового файла, то мы можем рассматривать поле FileField как любое обычное поле CharField.
Наконец, когда утилита была готова, я исправил методы клонирования и копирования в классе моделей Django, чтобы эти методы теперь были доступны для всех моделей в проекте.
Проблемы, с которыми я столкнулся
Самой большой проблемой, с которой я столкнулся , было копирование таких полей, как FileField
, ManyToManyField
и TreeForeignKey
. Написание действия копирования для них не было сложным, но когда мне пришлось взглянуть на минимизацию запроса к базе данных, это стало намного сложнее. Мне пришлось потратить много времени на мозговой штурм и прохождение кода этих полей, чтобы попытаться оптимизировать запросы.
Основные уроки
Самый большой урок из этого заключался в том, чтобы всегда иметь представление обо всех вариантах использования вашего проекта. Если бы я не потратил время на понимание и перечисление всех вариантов использования, мне пришлось бы продолжать добавлять материал каждый раз, когда добавлялось что-то новое. Я считаю, что чем больше изменений вы вносите в то, что должно было быть общим, тем больше вероятность появления в нем ошибок.
Советы и рекомендации
Мой совет кому – то-потратить достаточно времени на перо и бумагу, разрабатывая то, что вы собираетесь реализовать, каковы варианты использования и разрабатывая тестовые примеры для этого проекта. Всякий раз, когда вы начинаете что-то новое, мы хотим быстро перейти к кодированию, но наличие какой-то письменной работы только сделает кодирование более увлекательным и плавным.
Заключительные мысли и следующие шаги
Я не буду работать над этим в ближайшее время, потому что утилита клонирования завершена и может обрабатывать клонирование всех доступных полей.