Модель Django ON DELETE CASCADE policy, эмулируйте ON DELETE RESTRICT вместо этого, общее решение - PullRequest
3 голосов
/ 16 декабря 2009

Я хотел бы удалить экземпляр модели, но только если у него нет другого экземпляра другого класса с внешним ключом, указывающим на него. Из документации Django:

Когда Django удаляет объект, он имитирует поведение ограничения SQL ON DELETE CASCADE - другими словами, любые объекты, имеющие внешние ключи, указывающие на удаляемый объект, будут удалены вместе с ним.

В данном примере:

class TestA(models.Model)
    name = models.CharField()

class TestB(models.Model)
    name = models.CharField()
    TestAs = models.ManyToManyField(TestA)

# More classes with a ManyToMany relationship with TestA
# ........

Я бы хотел что-то вроде:

tA = TestA(name="testA1")
tB = TestB(name="testB1")
tB.testAs.add(tA)

t = TestA.objects.get(name="testA1")

if is_not_foreignkey(t):
    t.delete()
else:
    print "Error, some instance is using this"

Должен напечатать ошибку. Я знаю, что могу проверить конкретные экземпляры, которые устанавливает чужеродные ключи, например, в этом случае проверить t.TestB_set (), но я ищу более общее решение для любой данной модели.

Ответы [ 3 ]

2 голосов
/ 18 декабря 2009

Я наконец-то решил это, используя Nullable ForeignKeys и удалив ссылочный экземпляр модели , решение выглядит так:

    # Check foreign key references
    instances_to_be_deleted = CollectedObjects()
    object._collect_sub_objects(instances_to_be_deleted)

    # Count objects to delete
    count_instances_to_delete = 0
    for k in instances_to_be_deleted.unordered_keys():
        count_instances_to_delete += len(instances_to_be_deleted[k])

    if count_instances_to_delete == 1:
        object.delete()
    else:
        pass
0 голосов
/ 30 сентября 2014

CollectedObjects () было удалено в Django 1.3 - вот текущий метод:

from compiler.ast import flatten
from django.db import DEFAULT_DB_ALIAS
from django.contrib.admin.util import NestedObjects

def delete_obj_if_no_references(obj):
    collector = NestedObjects(using=DEFAULT_DB_ALIAS)
    collector.collect([obj])
    objs = flatten(collector.nested())
    if len(objs) == 1 and objs[0] is obj:
        obj.delete()
        return True
    return False
0 голосов
/ 16 декабря 2009

Проверка длины связанных объектов

t=TestA.objects.get(name="textA1")
if not t.testB_set.all().count():#related members
  t.delete()
...