что делает on delete на моделях Django?



Я довольно хорошо знаком с Django, но недавно заметил, что существует on_delete=models.CASCADE вариант с моделями, я искал документацию для того же, но не мог найти ничего больше, чем,




изменено в Django 1.9:



on_delete теперь можно использовать в качестве второго позиционного аргумента (ранее он обычно передавался только как аргумент ключевого слова). Это будет обязательным аргументом в Django 2.0.




an пример использования



from django.db import models

class Car(models.Model):
manufacturer = models.ForeignKey(
'Manufacturer',
on_delete=models.CASCADE,
)
# ...

class Manufacturer(models.Model):
# ...
pass


что on_delete ли? (угадайте действия, которые необходимо выполнить, если модель удалена)



что делает модели.Каскад сделать? (любые подсказки в документации)



какие еще варианты доступны (если моя догадка верна)?



где находится документация для этого?

1233   5  

5 ответов:

это поведение, чтобы принять, когда ссылка "объект" удаляется. Это не относится к django, это стандарт SQL.

есть 6 возможных действий, чтобы предпринять, когда такое событие происходит:

  • CASCADE: при удалении объекта, на который имеется ссылка, также удалите объекты, на которые имеются ссылки (например, при удалении сообщения в блоге может потребоваться также удалить комментарии). Эквивалент SQL: CASCADE.
  • PROTECT: запретить удаление объекта. Чтобы удалить его, вам придется удалить все объекты, которые ссылаются на него вручную. Эквивалентом SQL: RESTRICT.
  • SET_NULL: установите ссылку на NULL (требуется, чтобы поле было nullable). Например, когда вы удаляете пользователя, вы можете сохранить комментарии, которые он опубликовал в блоге, но сказать, что он был опубликован анонимным (или удаленным) пользователем. Эквивалентом SQL: SET NULL.
  • SET_DEFAULT: установить значение по умолчанию. Эквивалентом SQL: SET DEFAULT.
  • SET(...): установить заданное значение. Это не является частью стандарта SQL и полностью обрабатывается Django.
  • DO_NOTHING: вероятно, очень плохая идея, так как это создаст проблемы целостности в вашей базе данных (ссылка на объект, который на самом деле не существует). Эквивалентом SQL: NO ACTION.

источник: документация Django

см. также документация PostGreSQL например.

в большинстве случаев, CASCADE это ожидаемое поведение, но для каждого ForeignKey, вы всегда должны спросить себя, что такое ожидаемое поведение в этой ситуации. PROTECT и SET_NULL часто полезны. Установка CASCADE где он не должен, потенциально может удалить всю вашу базу данных в каскаде, просто удалив одного пользователя.

The on_delete метод используется для указания Django, что делать с экземплярами модели, которые зависят от экземпляра модели, который вы удаляете. (например, a ForeignKey отношения). Элемент on_delete=models.CASCADE говорит Django каскадировать эффект удаления, т. е. продолжить удаление зависимых моделей, а также.

вот более конкретный пример. Предположим, у вас есть Author модель, которая является ForeignKey на Book модель. Теперь, если вы удалите экземпляр Author модель, Джанго не будет знать, что делать с экземпляры Book модель, которая зависит от этого экземпляра Author - модели. Элемент on_delete метод говорит Джанго, что делать в этом случае. Установка on_delete=models.CASCADE проинструктирует Django каскадировать эффект удаления, т. е. удалить все Book экземпляры модели, которые зависят от Author экземпляр модели, который вы удалили.

Примечание: on_delete станет обязательным аргументом в Django 2.0. В более старых версиях он по умолчанию CASCADE.

вот весь официальная документация.

FYI, параметр on_delete в моделях находится в обратном направлении от того, как это звучит. Вы ставите "on_delete" на внешний ключ (FK) на модели, чтобы сказать django, что делать, если запись FK, на которую вы указываете в своей записи, удалена. Варианты, которые наш магазин использовал больше всего, - это защита, каскад и SET_NULL. Вот основные правила, которые я выяснил:

  1. используйте защиту, когда ваш FK указывает на таблицу поиска, которая действительно не должна меняться, и что конечно не должно привести к изменению таблицы. Если кто-то пытается удалить запись в этой таблице поиска, PROTECT предотвращает ее удаление, если она привязана к каким-либо записям. Это также предотвращает удаление django код запись только потому, что он удалил запись в таблице. Эта последняя часть имеет решающее значение. если бы кто-то удалил гендерную "женщину" из моей гендерной таблицы, я, конечно, не хотел бы, чтобы это мгновенно удаляло всех и всех людей, которых я имел мой личный стол, у которого был этот пол.
  2. используйте CASCADE, когда ваш FK указывает на "родительскую" запись. Итак, если у человека может быть много записей PersonEthnicity (он / она может быть американским индейцем, черным и белым), и этот человек и удалил, я действительно люблю!--5-->б хотите, чтобы все" дочерние " записи PersonEthnicity были удалены. Они не имеют значения без человека.
  3. используйте SET_NULL, когда вы do хотите, чтобы людям было разрешено удалить запись в таблице поиска, но вы все равно хотите сохранить свою запись. Например, если человек может иметь среднюю школу, но для меня не имеет значения, если эта средняя школа уходит на мой поисковый стол, я бы сказал "on_delete=SET_NULL."Это оставило бы мою личную запись там; это просто установило бы среднюю школу FK на моем лице в нуль. Очевидно, вам придется разрешить null=True на этом FK.

вот пример модели, которая делает все три вещи:

class PurchPurchaseAccount(models.Model):
    id = models.AutoField(primary_key=True)
    purchase = models.ForeignKey(PurchPurchase, null=True, db_column='purchase', blank=True, on_delete=models.CASCADE) # If "parent" rec gone, delete "child" rec!!!
    paid_from_acct = models.ForeignKey(PurchPaidFromAcct, null=True, db_column='paid_from_acct', blank=True, on_delete=models.PROTECT) # Disallow lookup deletion & do not delete this rec.
    _updated = models.DateTimeField()
    _updatedby = models.ForeignKey(Person, null=True, db_column='_updatedby', blank=True, related_name='acctupdated_by', on_delete=models.SET_NULL) # Person records shouldn't be deleted, but if they are, preserve this PurchPurchaseAccount entry, and just set this person to null.

    def __unicode__(self):
        return str(self.paid_from_acct.display)
    class Meta:
        db_table = u'purch_purchase_account'

как последний лакомый кусочек, знаете ли вы, что если вы не укажите on_delete (или нет), поведение по умолчанию-каскад? Это означает, что если кто-то удалил гендерную запись в вашей гендерной таблице, записи любого человека с этим полом также были удалены!

Я бы сказал: "Если вы сомневаетесь, установите on_delete=models.ЗАЩИЩАТЬ.- Тогда иди и проверь свое заявление. Вы быстро выясните, какие FKs должны быть помечены другими значениями, не подвергая опасности какие-либо ваших данных.

кроме того, стоит отметить, что on_delete=CASCADE фактически не добавляется ни к одной из ваших миграций, если это поведение, которое вы выбираете. Я думаю, это потому, что это по умолчанию, поэтому положить on_delete=CASCADE-это то же самое, что ничего не ставить.

вот ответ на ваш вопрос, который говорит: Почему мы используем on_delete?

при удалении объекта, на который ссылается ForeignKey, Django по умолчанию эмулирует поведение ограничения SQL на delete CASCADE, а также удаляет объект, содержащий ForeignKey. Это поведение можно переопределить, указав аргумент on_delete. Например, если у вас есть Nullable ForeignKey и вы хотите, чтобы он был установлен null, когда ссылочный объект удалено:

user = models.ForeignKey(User, blank=True, null=True, on_delete=models.SET_NULL)

возможные значения для on_delete находятся в django.децибел.модели:

каскад: каскадного удаления; по умолчанию.

защита: предотвратите удаление объекта ссылки, подняв ProtectedError, подкласс django.децибел.Честность.

SET_NULL: установите ForeignKey null; это возможно только в том случае, если null имеет значение True.

SET_DEFAULT: Set значение по умолчанию для внешнего ключа; значение по умолчанию для внешнего ключа должно быть установлено.

как упоминалось ранее, CASCADE удалит запись, которая имеет внешний ключ и ссылается на другой объект, который был удален. Так, например, если у вас есть сайт недвижимости и есть недвижимость, которая ссылается на город

class City(models.Model):
    # define model fields for a city

class Property(models.Model):
    city = models.ForeignKey(City, on_delete = models.CASCADE)
    # define model fields for a property

и теперь, когда город удаляется из базы данных, все связанные свойства (например. недвижимость, расположенная в этом городе) также будет удалена из базы данных

Теперь я также хочу упомянуть о достоинствах других опций, таких как SET_NULL или SET_DEFAULT или даже DO_NOTHING. В основном, с точки зрения администрирования, вы хотите "удалить" эти записи. Но на самом деле вы не хотите, чтобы они исчезли. По многим причинам. Кто-то удалил его случайно, или для аудита и мониторинга. И простая отчетность. Таким образом, это может быть способ "отключить" собственность от города. Опять же, это будет зависеть от того, как приложение написано.

например, в некоторых приложениях есть поле "удалено", которое равно 0 или 1. И все их поиск и просмотр списка и т. д., Все, что может отображаться в отчетах или в любом месте, где пользователь может получить доступ к нему с переднего конца, исключите все, что deleted == 1. Однако, если вы создаете пользовательский отчет или пользовательский запрос, чтобы вытащить список записей, которые были удалены, и даже более того, чтобы увидеть, когда он был в последний раз изменен (другое поле) и кем (т. е. кто удалил его и когда)..это очень выгодно с исполнительной точки зрения.

и не забывайте, что вы можете отменить случайное удаление так же просто, как deleted = 0 для тех записей.

моя точка зрения, если есть функциональность, всегда есть причина за ним. Не всегда хорошая причина. Но причина есть. И часто хороший тоже.

Comments

    Ничего не найдено.