Наследие
Среди различных типов наследства моделей ORM, ormar в настоящее время поддерживает два из них:
- Переместить
- Наследование конкретных таблиц (родительский параметр abstract=True)
Тип наследования
Краткое описание различных видов наследования:
- Mixins [Поддержка] -Не подстраивайте ormar.Model, просто определите поля, которые будут использоваться позднее в различных моделях (например, created_date и updated_date в каждой модели), таблицы создаются только в реальной модели, но добавьте поля в mixins
- наследование таблицы[SUPPORTED] -означает, что родительский родитель помечен как абстрактный, и каждый дочерний элемент имеет свою собственную таблицу, содержащую столбцы от родительского и собственного дочернего столбца, что-то похожее на Mixins, но родительский родитель также является моделью.
- Наследование одной таблицы[не поддерживается] -это означает, что создается только одна таблица, поля которой представляют собой комбинацию/сумму родительской модели и всех дочерних моделей, но в которой используется только подмножество столбцов в базе данных (все родительские модели и собственные столбцы, пропуская другие дочерние модели)
- Наследование нескольких/таблиц соединений[не поддерживается] -это означает, что некоторые столбцы сохраняются в родительской модели, а частично в подмодели, они связаны друг с другом одним на один, и обе модели немедленно работают в фоновом режиме
- Прокси-модель[не поддерживается] -означает, что только родительский элемент имеет реальную таблицу, а дочерний элемент просто добавляет методы, изменяет настройки и т. д.
Переместить
Чтобы использовать Mixins, просто определите класс, который не наследуется от ormar.Model, а определите ormar.Fields как переменную класса.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | |
!!!tip Обратите внимание, что Mixin не является моделью, поэтому вам все равно нужно наследовать ormar.Model и определить поле ormar_config в окончательной модели.
Класс категорий выше будет иметь четыре дополнительных поля: created_date, updated_date, created_by и Updated_by.
Создается только одна таблица для категории модели (категории), в которой поля класса категории категорий объединяются со всеми полями Mixins.
Обратите внимание, что Mixin в классе не является обязательным, но это хорошая практика Python.
Таблица Наследование
Концептуально наследование конкретных таблиц очень похоже на Mixins, но в качестве базового класса используется фактический ormar.Models.
!!!предупреждает, что базовый класс установил Abstract=True в объекте ormar_config и что при попытке наследовать из неабстрактного класса тегов будет выведена ошибка ModelDefinitionError.
Поскольку эта абстрактная модель никогда не инициализируется, вы можете пропустить метаданные и базы данных в ее определении ormar_config.
Но если вы предоставите его, он наследуется, так что вам не придется предоставлять метаданные и базы данных в окончательном/конкретном классе.
Обратите внимание, что при необходимости вы всегда можете перезаписать его в подклассы/классы.
Более того, по крайней мере, один класс в цепочке наследования должен предоставлять базу данных и метаданные-в противном случае это вызовет ошибку.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | |
Список наследуемых параметров/параметров выглядит следующим образом: метаданные, базы данных и зависимости.
Конечно, все поля базового класса объединяются и создаются в конкретных таблицах окончательной модели.
!!!tip Обратите внимание, что не обязательно указывать abstarct=False в окончательном классе-это значение по умолчанию, которое не наследуется.
Переопределение полей в подклассах
Обратите внимание, что вы можете переопределить ранее созданные поля так же, как и обычное наследование классов Python.
Каждый раз, когда задается поле с тем же именем и новым определением, оно полностью заменяет ранее определенные поля.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | |
!!!предупреждает, что при использовании зависимостей UniqueColumns окончательная модель должна объявить столбец с таким же именем. В противном случае будет выведена ошибка ModelDefinitionError.
1 2 3 4 5 6 | |
Наследственные отношения
Связь можно объявить на каждом этапе наследования, будь то в родительском или подклассе.
Когда связь определяется на уровне подмодели, она перезаписывает связь, определенную в родительской модели (если используется одно и то же имя поля), или, если определяется новое отношение, доступ к ней возможен только из этой подмодели.
При наследовании необходимо всегда помнить о параметре related_name, который должен быть уникальным в связанной модели при определении нескольких подклассов, наследующих одно и то же отношение.
Если параметр related_name не указан, ormar будет вычисляться для вас. Это относится к наследованию, так как все подмодели должны иметь разные имена классов, которые используются для вычисления related_name (class.name.lower()+'s') по умолчанию.
Однако, если указать related_name, это имя не может быть повторно использовано во всех подмоделях, так как они накладываются друг на друга на конце связанной модели.
Таким образом, у вас есть два варианта:
- Переопределение полей связей в подмодели и включение вручную другого параметра related_name
- позволяет ormar обрабатывать-> автоматически настраиваемый related_name: исходное related_name + "_" + имя таблицы подмодели
Это может показаться сложным, но давайте посмотрим на следующий пример:
Внешние связи
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | |
Теперь, когда вы проведете поля на модели Person, вы получите:
1 2 3 4 5 6 7 8 9 | |
Обратите внимание на то, что у вас есть поля грузовиков и автобусов, которые приводят к категории грузовиков и автобусов, принадлежащих данному человеку. Параметр related_name отсутствует, поэтому используется имя по умолчанию.
На автомобили, находящиеся в совместном владении, должны указываться в coowned_trucks и coowned_buses. Ormar добавляет суффиксы_trucks и_buses из названия таблицы подмоделей.
Звучит хорошо, но название по умолчанию для собственного грузовика хорошее (грузовик), но автобус некрасивый, так как мы можем его изменить?
Решение очень простое: достаточно переопределить поля в классе Bus и задать другой параметр related_name.
1 2 3 4 5 6 7 | |
Теперь столбы выглядят намного лучше.
1 2 3 4 5 6 7 8 9 | |
!!!Обратите внимание, что для поля владельца можно также указать related_name, чтобы добавить правильный суффикс.
1 2 3 | |
Много отношений
Точно так же вы можете наследовать модель, которая объявляет отношения ManyToMany, но с одним существенным отличием- Through Model.
Так как модель Through сможет сохранять другие поля и теперь связана только с двумя таблицами (из таблицы и из таблицы), каждый дочерний элемент, наследующий поле связи m2m, должен иметь отдельную модель Through.
Конечно, вы можете переопределить отношения в каждой подмодели, но это требует дополнительного кода и разрушает все наследование. Если вы согласны с соглашением об именовании по умолчанию, Ormar решит эту проблему за вас, и при необходимости вы можете изменить это соглашение вручную в дочернем элементе.
Опять же, давайте рассмотрим примеры, чтобы легче понять концепцию.
В предыдущем примере, описанном выше, изменим связь co_owners m2m.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | |
Ormar автоматически изменяет related_name поля таким образом, чтобы оно содержало подмодель. Имя по умолчанию-это исходное related_name + '_' + имя подтаблицы.
Таким образом, для класса Truck2 определяемая связь owner: Person = ormar.ForeignKey(Person, related_name="owned") становится owned_trucks2
Имя можно проверить, изучив список полей, существующих в модели человека.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | |
Но это еще не все. Это внутренняя структура ormar, но она влияет на структуру данных в базе данных, поэтому давайте проверим сквозные модели моделей Bus2 и Truck2.
1 2 3 4 5 6 7 8 9 | |
Как вы видели выше, ormar клонирует модель Through для каждого подкласса и добавляет имя подкласса в конце, а также изменяет имя таблицы для полей клонирования, используя имя таблицы для подкласса.
Обратите внимание, что исходная модель не только не используется, но и таблица модели удаляется из метаданных:
1 2 3 | |
Поэтому обратите внимание на то, что если вы вводите наследование и преобразуете модель в абстрактную родительскую модель, то вы можете потерять данные в таблице, если вы не будете осторожны.
!!!Примечание Примечание: Исходное имя таблицы и имя модели с Through никогда не использовались. Создаются и используются только таблицы с клонами.
!!!предупреждает, что каждый подкласс модели, который определяет отношения ManyToMany, создает новую Through модель, что также означает новые таблицы базы данных.
1 2 | |
Исключить родительские поля
Ormar позволяет пропустить некоторые поля в унаследованной модели из родительской модели.
!!!Обратите внимание, что одно и то же поведение может быть достигнуто, разбив модель на более абстрактные модели и миксин-это предпочтительный способ в обычных ситуациях.
Чтобы пропустить некоторые поля в подмодели, перечислите все поля, которые необходимо пропустить, следующие параметры model.ormar_config.exclude_parent_fields:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | |
Обратите внимание на то, что необходимо указать только имя поля, которое исключает родительское поле независимо от того, из какой родительской модели оно исходит.
!!!Обратите внимание на то, что если требуется перезаписать поле в подмодели, то не обязательно исключать его, просто перезаписать объявление поля в подмодели с тем же именем поля.
Обратите внимание на то, что такое поведение может запутать функцию mypy и статический инспектор типов, но доступ к несуществующим полям не будет работать во время выполнения. Вот почему предпочтение отдается разделению базового класса.
Такой же эффект достигается путем разделения базового класса, например:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | |
Таким образом, при необходимости можно наследовать только один из классов, созданных и обновленных. В противном случае можно наследовать только один класс.