Я хорошо знаком с Django, но недавно заметил, что существует on_delete=models.CASCADE
опция с моделями, я искал документацию для того же самого, но не мог найти ничего больше, чем:
Изменено в Django 1.9:
on_delete
теперь может использоваться в качестве второго позиционного аргумента (ранее он обычно передавался только в качестве ключевого аргумента). Это будет обязательный аргумент в Django 2.0.
from django.db import models
class Car(models.Model):
manufacturer = models.ForeignKey(
'Manufacturer',
on_delete=models.CASCADE,
)
# ...
class Manufacturer(models.Model):
# ...
pass
Что делает on_delete? ( Я думаю, что действия будут сделаны, если модель будет удалена )
Что делает models.CASCADE
? ( любые намеки в документации )
Какие еще варианты доступны ( если мои предположения верны )?
Где находится документация для этого?
python
django
django-models
Все это Ваити
источник
источник
Ответы:
Это поведение, которое нужно применять при удалении ссылочного объекта. Это не специфично для django, это стандарт SQL.
Есть 6 возможных действий при возникновении такого события:
CASCADE
: При удалении ссылочного объекта также удаляются объекты, на которые есть ссылки (например, когда вы удаляете сообщение в блоге, вы также можете удалить комментарии). SQL эквивалент:CASCADE
.PROTECT
: Запретить удаление указанного объекта. Чтобы удалить его, вам придется удалить все объекты, которые ссылаются на него вручную. SQL эквивалент:RESTRICT
.SET_NULL
: Установить ссылку на NULL (требуется, чтобы поле было обнуляемым). Например, когда вы удаляете пользователя, вы можете захотеть сохранить комментарии, которые он опубликовал в сообщениях блога, но сказать, что он был опубликован анонимным (или удаленным) пользователем. SQL эквивалент:SET NULL
.SET_DEFAULT
: Установить значение по умолчанию. SQL эквивалент:SET DEFAULT
.SET(...)
: Установить заданное значение. Этот не является частью стандарта SQL и полностью обрабатывается Django.DO_NOTHING
Возможно, это очень плохая идея, поскольку это может создать проблемы целостности в вашей базе данных (ссылки на объект, который на самом деле не существует). SQL эквивалент:NO ACTION
.Источник: документация Django
См. Также документацию PostGreSQL, например.
В большинстве случаев
CASCADE
это ожидаемое поведение, но для каждого ForeignKey вы всегда должны спросить себя, каково ожидаемое поведение в этой ситуации.PROTECT
иSET_NULL
часто полезны. Установка,CASCADE
где это не должно, потенциально может удалить всю вашу базу данных в каскаде, просто удалив одного пользователя.Дополнительное примечание для уточнения каскадного направления
Забавно заметить, что направление
CASCADE
действия многим не понятно. На самом деле, это забавно отметить , что толькоCASCADE
действие не ясно. Я понимаю, что каскадное поведение может сбивать с толку, однако вы должны думать, что это то же направление, что и любое другое действие . Таким образом, если вы чувствуете, что этоCASCADE
направление неясно для вас, это фактически означает, чтоon_delete
поведение вам неясно.В вашей базе данных внешний ключ в основном представлен целочисленным полем, значение которого является первичным ключом внешнего объекта. Допустим, у вас есть запись comment_A , которая имеет внешний ключ к записи article_B . Если вы удаляете запись comment_A , все в порядке, article_B имел обыкновение жить без comment_A и не беспокоиться, если он удален. Однако, если вы удалите article_B , то comment_A паникует! Он никогда не жил без article_B и нуждается в нем, он является частью его атрибутов (
article=article_B
но что такое * article_B ** ???). Это гдеon_delete
шаги, чтобы определить, как устранить эту ошибку целостностиЛибо говоря:PROTECT
на языке SQL)SET_NULL
)CASCADE
поведение).SET_DEFAULT
или дажеSET(...)
).DO_NOTHING
)Я надеюсь, что это делает каскадное направление более ясным. :)
источник
Comment
есть внешний ключ,BlogPost
то при удалении BlogPost следует удалить комментарий, но удаление комментария не должно удалять BlogPost вне зависимости от RDMS?Comment
, кто имеет поле FK в своей таблице, в то время какBlogPost
«владеет»,Comment
если мы говорим о реальной модели. Хорошо.Этот
on_delete
метод используется для указания Django, что делать с экземплярами модели, которые зависят от удаляемого экземпляра модели. (например,ForeignKey
отношения).on_delete=models.CASCADE
Говорит Джанго , чтобы обрушивать УДАЛЕНИЕ эффект т.е. продолжить удаление зависимых моделей , а также.Вот более конкретный пример. Предположим, у вас есть
Author
модель, которая естьForeignKey
вBook
модели. Теперь, если вы удалите экземплярAuthor
модели, Django не будет знать, что делать с экземплярамиBook
модели, которые зависят от этого экземпляраAuthor
модели.on_delete
Метод говорит Джанго , что делать в этом случае. Параметрon_delete=models.CASCADE
даст Django каскадный эффект удаления, т.е. удалит всеBook
экземпляры модели, которые зависят отAuthor
удаленного экземпляра модели.Примечание:
on_delete
станет обязательным аргументом в Django 2.0. В старых версиях по умолчаниюCASCADE
.Вот вся официальная документация.
источник
К вашему сведению,
on_delete
параметр в моделях обратен тому, на что это похоже. Вы надеваетеon_delete
внешний ключ (FK) на модель, чтобы сообщить django, что делать, если запись FK, на которую вы указываете в своей записи, удалена. Варианты нашего магазина использовали большинство из нихPROTECT
,CASCADE
иSET_NULL
. Вот основные правила, которые я выяснил:PROTECT
когда ваш FK указывает на справочную таблицу, которая на самом деле не должна меняться и которая, безусловно, не должна вызывать изменения вашей таблицы. Если кто-то пытается удалить запись в этой справочной таблице, онPROTECT
не может удалить ее, если она связана с какими-либо записями. Это также не позволяет django удалить вашу запись только потому, что она удалила запись в справочной таблице. Эта последняя часть имеет решающее значение. Если бы кто-то удалил пол «Женщина» из моей таблицы «Гендер», Я бы НЕ хотел, чтобы это мгновенно удаляло всех и всех людей, которые были у меня в таблице «Персона», которые имели этот пол.CASCADE
когда ваш FK указывает на «родительскую» запись. Таким образом, если у Person может быть много записей PersonEthnicity (он может быть американским индейцем, чернокожим и белым), и этот Person будет удален, я действительно хотел бы удалить любые "дочерние" записи PersonEthnicity. Они не имеют отношения к личности.SET_NULL
если вы хотите, чтобы людям было разрешено удалить запись в справочной таблице, но вы все равно хотите сохранить свою запись. Например, если у человека может быть старшая школа, но для меня не имеет значения, уйдет ли эта старшая школа на мою таблицу поиска, я бы сказалon_delete=SET_NULL
. Это оставило бы мою личную запись там; это просто установило бы для моей персоны среднюю школу FK на ноль. Очевидно, вам придется допуститьnull=True
на этом FK.Вот пример модели, которая делает все три вещи:
Как последний лакомый кусочек, знаете ли вы, что, если вы не укажете
on_delete
(или не указали ), поведение по умолчанию будетCASCADE
? Это означает, что если кто-то удалил запись о полах в вашей таблице «Гендер», все записи о персонах с этим полом также будут удалены!Я бы сказал: «Если сомневаешься, поставь
on_delete=models.PROTECT
». Тогда иди протестируй свое приложение. Вы быстро выясните, какие FK должны быть помечены другими значениями, не подвергая опасности какие-либо ваши данные.Также стоит отметить, что
on_delete=CASCADE
на самом деле это не добавляется ни к одной из ваших миграций, если вы выбираете именно такое поведение. Я предполагаю, что это потому, что это значение по умолчанию, поэтому установкаon_delete=CASCADE
- это то же самое, что установка ничего.источник
Как упоминалось ранее, CASCADE удалит запись, которая имеет внешний ключ, и ссылается на другой объект, который был удален. Так, например, если у вас есть сайт по недвижимости и у вас есть недвижимость, которая ссылается на город
и теперь, когда Город удален из базы данных, все связанные Свойства (например, недвижимость, расположенная в этом городе) также будут удалены из базы данных.
Теперь я также хочу упомянуть о достоинствах других опций, таких как SET_NULL или SET_DEFAULT или даже DO_NOTHING. По сути, с точки зрения администрации, вы хотите «удалить» эти записи. Но вы не хотите, чтобы они исчезли. По многим причинам. Кто-то мог удалить его случайно или для аудита и мониторинга. И простая отчетность. Так что это может быть способ «отключить» собственность от города. Опять же, это будет зависеть от того, как написано ваше приложение.
Например, некоторые приложения имеют поле «удалено», которое равно 0 или 1. И все их поиски, представления списков и т. Д., Все, что может появиться в отчетах или где угодно пользователь может получить к нему доступ из внешнего интерфейса, исключить все, что есть
deleted == 1
. Однако, если вы создаете пользовательский отчет или пользовательский запрос, чтобы раскрыть список записей, которые были удалены, и даже более того, чтобы увидеть, когда он был последний раз изменен (другое поле) и кем (то есть, кто его удалил и когда). это очень выгодно с точки зрения исполнительной власти.И не забывайте, что вы можете отменить случайное удаление так же просто, как и
deleted = 0
для этих записей.Я хочу сказать, что если есть функциональность, то всегда есть причина. Не всегда веская причина. Но причина. И часто хороший тоже.
источник
Вот ответ на ваш вопрос, который говорит: почему мы используем on_delete?
Когда объект, на который ссылается ForeignKey, удаляется, Django по умолчанию эмулирует поведение ограничения SQL ON DELETE CASCADE, а также удаляет объект, содержащий ForeignKey. Это поведение можно изменить, указав аргумент on_delete. Например, если у вас есть Nullable ForeignKey, и вы хотите, чтобы он был установлен равным NULL при удалении ссылочного объекта:
Возможные значения on_delete находятся в django.db.models:
КАСКАД: Каскад удаляет; по умолчанию.
PROTECT: Предотвратить удаление объекта, на который есть ссылка, подняв ProtectedError, подкласс django.db.IntegrityError.
SET_NULL: установить значение ForeignKey пустым; это возможно только в том случае, если null равен True.
SET_DEFAULT: установить ForeignKey в значение по умолчанию; значение по умолчанию для ForeignKey должно быть установлено.
источник
Допустим, у вас есть две модели, одна с именем Person и другая с именем Companies .
По определению, один человек может создать более одной компании.
Учитывая, что в компании может быть один и только один человек, мы хотим, чтобы при удалении человека все компании, связанные с этим человеком, также были удалены.
Итак, мы начинаем с создания модели Person, как это
Тогда модель компании может выглядеть так
Обратите внимание на использование
on_delete=models.CASCADE
в моделях компаний. То есть, чтобы удалить все компании, когда лицо, которому он принадлежит (экземпляр класса Person), удаляется.источник
Переориентируйте свою ментальную модель функциональности «КАСКАД», подумав о добавлении ФК к уже существующему каскаду (то есть водопаду). Источником этого водопада является первичный ключ. Удаляет поток вниз.
Поэтому, если вы определяете on_delete FK как «CASCADE», вы добавляете запись этого FK в каскад удалений, происходящих из PK. Запись FK может участвовать в этом каскаде или нет («SET_NULL»). На самом деле, запись с FK может даже предотвратить поток удалений! Постройте плотину с помощью «ЗАЩИТА».
источник
Использование CASCADE означает на самом деле указание Django удалить указанную запись. В приведенном ниже примере приложения для опроса: когда «Вопрос» удаляется, он также удаляет варианты, которые есть у этого Вопроса.
например, вопрос: как вы узнали о нас? (Выбор: 1. Друзья 2. Телевизионная реклама 3. Поисковая система 4. Электронная реклама)
Когда вы удалите этот вопрос, он также удалит все эти четыре варианта из таблицы. Обратите внимание, в каком направлении он течет. Вам не нужно помещать on_delete = models.CASCADE в Question Model, чтобы выбрать его.
источник