Подтвердить что ты не робот

Как создать модель Django с помощью ForeignKeys, которая не каскадирует, удаляет ее дочерние элементы?

Одна из моих моделей, которая имеет ForeignKey, фактически является представлением MySQL для других таблиц. Проблема, с которой я сталкиваюсь, заключается в том, что когда я удаляю данные из этих таблиц, Django, как описано в документации "удаление объектов" ...

Когда Django удаляет объект, он эмулирует поведение SQL ограничение УДАЛИТЬ КАСКАД - в другими словами, любые объекты, которые внешние ключи, указывающие на объект будут удалены вместе с он.

... пытается удалить строки из моего представления, что, конечно, не может, и поэтому выдает ошибку:

mysql_exceptions.OperationalError '>=(1395, "Can not delete from join view 'my_db.my_mysql_view'"'

Можно ли указать ограничение ForeignKey на модель, которая предоставит мне все мастерство Django, но не будет каскадно удалять на нее? Или, есть ли способ попросить MySQL игнорировать команды для удаления строки из моего представления вместо повышения ошибки?

4b9b3361

Ответ 1

Гарольд ответил мне в правильном направлении. Это эскиз на том, как я его реализовал (на французской старой базе данных, а значит, на нечетном соглашении об именах):
class Factures(models.Model):
    idFacture = models.IntegerField(primary_key=True)
    idLettrage = models.ForeignKey('Lettrage', db_column='idLettrage', null=True, blank=True)

class Paiements(models.Model):
    idPaiement = models.IntegerField(primary_key=True)
    idLettrage = models.ForeignKey('Lettrage', db_column='idLettrage', null=True, blank=True)

class Lettrage(models.Model):
    idLettrage = models.IntegerField(primary_key=True)

    def delete(self):
        """Dettaches factures and paiements from current lettre before deleting"""
        self.factures_set.clear()
        self.paiements_set.clear()
        super(Lettrage, self).delete()

Ответ 2

Django 1.3a1 и поддержите это через ForeignKey on_delete.

В следующем примере задается поле NULL при удалении внешнего ключа. Подробнее см. В документации .

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

Ответ 3

У менеджера Django ForeignKey есть метод clear(), который удаляет все объекты из соответствующего набора объектов. Вызов сначала, а затем удаление вашего объекта должно работать. Зависимые объекты будут иметь свои внешние ключи равными None (если разрешено в вашей модели).

Краткое описание здесь: http://docs.djangoproject.com/en/dev/topics/db/queries/#following-relationships-backward

Ответ 4

FYI - запрос функции для этого существует в репозитории источника django в http://code.djangoproject.com/ticket/7539. Похоже, эта тема получает некоторое внимание. Надеюсь, он будет включен в будущие выпуски Django.

Билет включает в себя патчи к ядру Django для реализации необязательного параметра "on_delete" для моделей. ForeignKey (...), который позволяет вам указать, что происходит, когда удаленная ссылка на "Модель" удалена, включая отмену поведения по умолчанию DEL DELETE CASCADE.

Ответ 5

Ну, глядя на метод удаления

def delete(self):
    assert self._get_pk_val() is not None, "%s object can't be deleted because its %s attribute is set to None." % (self._meta.object_name, self._meta.pk.attname)

    # Find all the objects than need to be deleted.
    seen_objs = CollectedObjects()
    self._collect_sub_objects(seen_objs)

    # Actually delete the objects.
    delete_objects(seen_objs)

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

def delete(self):
    assert self._get_pk_val() is not None, "%s object can't be deleted because its %s attribute is set to None." % (self._meta.object_name, self._meta.pk.attname)

    # Find all the objects than need to be deleted.
    seen_objs = CollectedObjects()
    seen_objs.add(model=self.__class__, pk=self.pk, obj=self, parent_model=None)

    # Actually delete the objects.
    delete_objects(seen_objs)

Ответ 6

Один из способов заключается в вызове clear метода перед удалением документации здесь, который в основном "очищает" отношения. Одна проблема мысли: она не авто сама по себе. Вы можете выбрать: называть его каждый раз, когда вы не хотите каскада, или использовать сигнал pre_delete для отправки сообщения перед каждым удалением, конечно, это вызовет проблемы, когда вы хотите удалить - каскад.

Или вы можете внести вклад в сообщество django и добавить аргумент ключевого слова для удаления, возможно, он будет в django 1.3?: D

Ответ 7

Re: http://code.djangoproject.com/ticket/7539

Нет внимания на Django 1.2.1, июнь 2010 года. Думаю, нам нужно "посмотреть это пространство".